Auto merge of #77430 - ecstatic-morse:mir-source-in-body, r=lcnr
Store a `MirSource` inside every `Body` Resolves #77427. r? `@ghost`
This commit is contained in:
commit
4ccf5f731b
|
@ -10,12 +10,11 @@ use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||||
use crate::ty::print::{FmtPrinter, Printer};
|
use crate::ty::print::{FmtPrinter, Printer};
|
||||||
use crate::ty::subst::{Subst, SubstsRef};
|
use crate::ty::subst::{Subst, SubstsRef};
|
||||||
use crate::ty::{
|
use crate::ty::{self, List, Ty, TyCtxt};
|
||||||
self, AdtDef, CanonicalUserTypeAnnotations, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex,
|
use crate::ty::{AdtDef, InstanceDef, Region, UserTypeAnnotationIndex};
|
||||||
};
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, Namespace};
|
use rustc_hir::def::{CtorKind, Namespace};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||||
use rustc_hir::{self, GeneratorKind};
|
use rustc_hir::{self, GeneratorKind};
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
|
|
||||||
|
@ -112,6 +111,38 @@ impl MirPhase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Where a specific `mir::Body` comes from.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable)]
|
||||||
|
pub struct MirSource<'tcx> {
|
||||||
|
pub instance: InstanceDef<'tcx>,
|
||||||
|
|
||||||
|
/// If `Some`, this is a promoted rvalue within the parent function.
|
||||||
|
pub promoted: Option<Promoted>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> MirSource<'tcx> {
|
||||||
|
pub fn item(def_id: DefId) -> Self {
|
||||||
|
MirSource {
|
||||||
|
instance: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
|
||||||
|
promoted: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_instance(instance: InstanceDef<'tcx>) -> Self {
|
||||||
|
MirSource { instance, promoted: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
|
||||||
|
self.instance.with_opt_param()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn def_id(&self) -> DefId {
|
||||||
|
self.instance.def_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The lowered representation of a single function.
|
/// The lowered representation of a single function.
|
||||||
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)]
|
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)]
|
||||||
pub struct Body<'tcx> {
|
pub struct Body<'tcx> {
|
||||||
|
@ -126,6 +157,8 @@ pub struct Body<'tcx> {
|
||||||
/// us to see the difference and forego optimization on the inlined promoted items.
|
/// us to see the difference and forego optimization on the inlined promoted items.
|
||||||
pub phase: MirPhase,
|
pub phase: MirPhase,
|
||||||
|
|
||||||
|
pub source: MirSource<'tcx>,
|
||||||
|
|
||||||
/// A list of source scopes; these are referenced by statements
|
/// A list of source scopes; these are referenced by statements
|
||||||
/// and used for debuginfo. Indexed by a `SourceScope`.
|
/// and used for debuginfo. Indexed by a `SourceScope`.
|
||||||
pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
|
pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
|
||||||
|
@ -151,7 +184,7 @@ pub struct Body<'tcx> {
|
||||||
pub local_decls: LocalDecls<'tcx>,
|
pub local_decls: LocalDecls<'tcx>,
|
||||||
|
|
||||||
/// User type annotations.
|
/// User type annotations.
|
||||||
pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
|
pub user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
|
||||||
|
|
||||||
/// The number of arguments this function takes.
|
/// The number of arguments this function takes.
|
||||||
///
|
///
|
||||||
|
@ -209,10 +242,11 @@ pub struct Body<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> Body<'tcx> {
|
impl<'tcx> Body<'tcx> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
source: MirSource<'tcx>,
|
||||||
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
||||||
source_scopes: IndexVec<SourceScope, SourceScopeData>,
|
source_scopes: IndexVec<SourceScope, SourceScopeData>,
|
||||||
local_decls: LocalDecls<'tcx>,
|
local_decls: LocalDecls<'tcx>,
|
||||||
user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
|
user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
var_debug_info: Vec<VarDebugInfo<'tcx>>,
|
var_debug_info: Vec<VarDebugInfo<'tcx>>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -228,6 +262,7 @@ impl<'tcx> Body<'tcx> {
|
||||||
|
|
||||||
let mut body = Body {
|
let mut body = Body {
|
||||||
phase: MirPhase::Build,
|
phase: MirPhase::Build,
|
||||||
|
source,
|
||||||
basic_blocks,
|
basic_blocks,
|
||||||
source_scopes,
|
source_scopes,
|
||||||
yield_ty: None,
|
yield_ty: None,
|
||||||
|
@ -257,6 +292,7 @@ impl<'tcx> Body<'tcx> {
|
||||||
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
|
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
|
||||||
let mut body = Body {
|
let mut body = Body {
|
||||||
phase: MirPhase::Build,
|
phase: MirPhase::Build,
|
||||||
|
source: MirSource::item(DefId::local(CRATE_DEF_INDEX)),
|
||||||
basic_blocks,
|
basic_blocks,
|
||||||
source_scopes: IndexVec::new(),
|
source_scopes: IndexVec::new(),
|
||||||
yield_ty: None,
|
yield_ty: None,
|
||||||
|
|
|
@ -22,7 +22,8 @@ pub struct Instance<'tcx> {
|
||||||
pub substs: SubstsRef<'tcx>,
|
pub substs: SubstsRef<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable)]
|
||||||
pub enum InstanceDef<'tcx> {
|
pub enum InstanceDef<'tcx> {
|
||||||
/// A user-defined callable item.
|
/// A user-defined callable item.
|
||||||
///
|
///
|
||||||
|
|
|
@ -17,7 +17,7 @@ use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind
|
||||||
use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
|
use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
|
||||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::{self, InstanceDef, ParamEnv, RegionVid, TyCtxt};
|
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt};
|
||||||
use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT};
|
use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT};
|
||||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathInd
|
||||||
use crate::dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError};
|
use crate::dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError};
|
||||||
use crate::dataflow::MoveDataParamEnv;
|
use crate::dataflow::MoveDataParamEnv;
|
||||||
use crate::dataflow::{Analysis, BorrowckFlowState as Flows, BorrowckResults};
|
use crate::dataflow::{Analysis, BorrowckFlowState as Flows, BorrowckResults};
|
||||||
use crate::transform::MirSource;
|
|
||||||
|
|
||||||
use self::diagnostics::{AccessKind, RegionName};
|
use self::diagnostics::{AccessKind, RegionName};
|
||||||
use self::location::LocationTable;
|
use self::location::LocationTable;
|
||||||
|
@ -236,13 +235,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
||||||
|
|
||||||
// Dump MIR results into a file, if that is enabled. This let us
|
// Dump MIR results into a file, if that is enabled. This let us
|
||||||
// write unit-tests, as well as helping with debugging.
|
// write unit-tests, as well as helping with debugging.
|
||||||
nll::dump_mir_results(
|
nll::dump_mir_results(infcx, &body, ®ioncx, &opt_closure_req);
|
||||||
infcx,
|
|
||||||
MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None },
|
|
||||||
&body,
|
|
||||||
®ioncx,
|
|
||||||
&opt_closure_req,
|
|
||||||
);
|
|
||||||
|
|
||||||
// We also have a `#[rustc_regions]` annotation that causes us to dump
|
// We also have a `#[rustc_regions]` annotation that causes us to dump
|
||||||
// information.
|
// information.
|
||||||
|
|
|
@ -9,7 +9,7 @@ use rustc_middle::mir::{
|
||||||
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
|
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
|
||||||
Promoted,
|
Promoted,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, InstanceDef, RegionKind, RegionVid};
|
use rustc_middle::ty::{self, RegionKind, RegionVid};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
@ -24,7 +24,6 @@ use polonius_engine::{Algorithm, Output};
|
||||||
use crate::dataflow::impls::MaybeInitializedPlaces;
|
use crate::dataflow::impls::MaybeInitializedPlaces;
|
||||||
use crate::dataflow::move_paths::{InitKind, InitLocation, MoveData};
|
use crate::dataflow::move_paths::{InitKind, InitLocation, MoveData};
|
||||||
use crate::dataflow::ResultsCursor;
|
use crate::dataflow::ResultsCursor;
|
||||||
use crate::transform::MirSource;
|
|
||||||
use crate::util as mir_util;
|
use crate::util as mir_util;
|
||||||
use crate::util::pretty;
|
use crate::util::pretty;
|
||||||
|
|
||||||
|
@ -72,8 +71,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
|
||||||
// Replace all remaining regions with fresh inference variables.
|
// Replace all remaining regions with fresh inference variables.
|
||||||
renumber::renumber_mir(infcx, body, promoted);
|
renumber::renumber_mir(infcx, body, promoted);
|
||||||
|
|
||||||
let source = MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None };
|
mir_util::dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(()));
|
||||||
mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(()));
|
|
||||||
|
|
||||||
universal_regions
|
universal_regions
|
||||||
}
|
}
|
||||||
|
@ -315,16 +313,15 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
||||||
|
|
||||||
pub(super) fn dump_mir_results<'a, 'tcx>(
|
pub(super) fn dump_mir_results<'a, 'tcx>(
|
||||||
infcx: &InferCtxt<'a, 'tcx>,
|
infcx: &InferCtxt<'a, 'tcx>,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
regioncx: &RegionInferenceContext<'tcx>,
|
regioncx: &RegionInferenceContext<'tcx>,
|
||||||
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
|
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
|
||||||
) {
|
) {
|
||||||
if !mir_util::dump_enabled(infcx.tcx, "nll", source.def_id()) {
|
if !mir_util::dump_enabled(infcx.tcx, "nll", body.source.def_id()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mir_util::dump_mir(infcx.tcx, None, "nll", &0, source, body, |pass_where, out| {
|
mir_util::dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| {
|
||||||
match pass_where {
|
match pass_where {
|
||||||
// Before the CFG, dump out the values for each region variable.
|
// Before the CFG, dump out the values for each region variable.
|
||||||
PassWhere::BeforeCFG => {
|
PassWhere::BeforeCFG => {
|
||||||
|
@ -352,14 +349,14 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
|
||||||
// Also dump the inference graph constraints as a graphviz file.
|
// Also dump the inference graph constraints as a graphviz file.
|
||||||
let _: io::Result<()> = try {
|
let _: io::Result<()> = try {
|
||||||
let mut file =
|
let mut file =
|
||||||
pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, source)?;
|
pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?;
|
||||||
regioncx.dump_graphviz_raw_constraints(&mut file)?;
|
regioncx.dump_graphviz_raw_constraints(&mut file)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Also dump the inference graph constraints as a graphviz file.
|
// Also dump the inference graph constraints as a graphviz file.
|
||||||
let _: io::Result<()> = try {
|
let _: io::Result<()> = try {
|
||||||
let mut file =
|
let mut file =
|
||||||
pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, source)?;
|
pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?;
|
||||||
regioncx.dump_graphviz_scc_constraints(&mut file)?;
|
regioncx.dump_graphviz_scc_constraints(&mut file)?;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,8 +78,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
|
||||||
run_passes(
|
run_passes(
|
||||||
tcx,
|
tcx,
|
||||||
&mut result,
|
&mut result,
|
||||||
instance,
|
|
||||||
None,
|
|
||||||
MirPhase::Const,
|
MirPhase::Const,
|
||||||
&[&[
|
&[&[
|
||||||
&add_moves_for_packed_drops::AddMovesForPackedDrops,
|
&add_moves_for_packed_drops::AddMovesForPackedDrops,
|
||||||
|
@ -163,7 +161,9 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
||||||
block(&mut blocks, TerminatorKind::Goto { target: return_block });
|
block(&mut blocks, TerminatorKind::Goto { target: return_block });
|
||||||
block(&mut blocks, TerminatorKind::Return);
|
block(&mut blocks, TerminatorKind::Return);
|
||||||
|
|
||||||
let mut body = new_body(blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
|
let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty));
|
||||||
|
let mut body =
|
||||||
|
new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
|
||||||
|
|
||||||
if let Some(..) = ty {
|
if let Some(..) = ty {
|
||||||
// The first argument (index 0), but add 1 for the return value.
|
// The first argument (index 0), but add 1 for the return value.
|
||||||
|
@ -202,12 +202,14 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_body<'tcx>(
|
fn new_body<'tcx>(
|
||||||
|
source: MirSource<'tcx>,
|
||||||
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
||||||
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Body<'tcx> {
|
) -> Body<'tcx> {
|
||||||
Body::new(
|
Body::new(
|
||||||
|
source,
|
||||||
basic_blocks,
|
basic_blocks,
|
||||||
IndexVec::from_elem_n(
|
IndexVec::from_elem_n(
|
||||||
SourceScopeData { span, parent_scope: None, local_data: ClearCrossCrate::Clear },
|
SourceScopeData { span, parent_scope: None, local_data: ClearCrossCrate::Clear },
|
||||||
|
@ -344,7 +346,11 @@ impl CloneShimBuilder<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_mir(self) -> Body<'tcx> {
|
fn into_mir(self) -> Body<'tcx> {
|
||||||
new_body(self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
|
let source = MirSource::from_instance(ty::InstanceDef::CloneShim(
|
||||||
|
self.def_id,
|
||||||
|
self.sig.inputs_and_output[0],
|
||||||
|
));
|
||||||
|
new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source_info(&self) -> SourceInfo {
|
fn source_info(&self) -> SourceInfo {
|
||||||
|
@ -834,7 +840,8 @@ fn build_call_shim<'tcx>(
|
||||||
block(&mut blocks, vec![], TerminatorKind::Resume, true);
|
block(&mut blocks, vec![], TerminatorKind::Resume, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut body = new_body(blocks, local_decls, sig.inputs().len(), span);
|
let mut body =
|
||||||
|
new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span);
|
||||||
|
|
||||||
if let Abi::RustCall = sig.abi {
|
if let Abi::RustCall = sig.abi {
|
||||||
body.spread_arg = Some(Local::new(sig.inputs().len()));
|
body.spread_arg = Some(Local::new(sig.inputs().len()));
|
||||||
|
@ -897,18 +904,16 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
|
||||||
is_cleanup: false,
|
is_cleanup: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let body =
|
let source = MirSource::item(ctor_id);
|
||||||
new_body(IndexVec::from_elem_n(start_block, 1), local_decls, sig.inputs().len(), span);
|
let body = new_body(
|
||||||
|
source,
|
||||||
crate::util::dump_mir(
|
IndexVec::from_elem_n(start_block, 1),
|
||||||
tcx,
|
local_decls,
|
||||||
None,
|
sig.inputs().len(),
|
||||||
"mir_map",
|
span,
|
||||||
&0,
|
|
||||||
crate::transform::MirSource::item(ctor_id),
|
|
||||||
&body,
|
|
||||||
|_, _| Ok(()),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
crate::util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
|
||||||
|
|
||||||
body
|
body
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -31,7 +31,7 @@ pub use self::AddCallGuards::*;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for AddCallGuards {
|
impl<'tcx> MirPass<'tcx> for AddCallGuards {
|
||||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
self.add_call_guards(body);
|
self.add_call_guards(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use crate::util::patch::MirPatch;
|
use crate::util::patch::MirPatch;
|
||||||
|
|
||||||
|
@ -40,9 +40,9 @@ use crate::util::patch::MirPatch;
|
||||||
pub struct AddMovesForPackedDrops;
|
pub struct AddMovesForPackedDrops;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops {
|
impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span);
|
debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span);
|
||||||
add_moves_for_packed_drops(tcx, body, src.def_id());
|
add_moves_for_packed_drops(tcx, body, body.source.def_id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//! of MIR building, and only after this pass we think of the program has having the
|
//! of MIR building, and only after this pass we think of the program has having the
|
||||||
//! normal MIR semantics.
|
//! normal MIR semantics.
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
|
|
||||||
|
@ -58,13 +58,13 @@ fn may_be_reference(ty: Ty<'tcx>) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for AddRetag {
|
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>, body: &mut Body<'tcx>) {
|
||||||
if !tcx.sess.opts.debugging_opts.mir_emit_retag {
|
if !tcx.sess.opts.debugging_opts.mir_emit_retag {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need an `AllCallEdges` pass before we can do any work.
|
// We need an `AllCallEdges` pass before we can do any work.
|
||||||
super::add_call_guards::AllCallEdges.run_pass(tcx, src, body);
|
super::add_call_guards::AllCallEdges.run_pass(tcx, body);
|
||||||
|
|
||||||
let (span, arg_count) = (body.span, body.arg_count);
|
let (span, arg_count) = (body.span, body.arg_count);
|
||||||
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
|
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
|
||||||
|
|
|
@ -6,12 +6,12 @@ use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::lint::builtin::CONST_ITEM_MUTATION;
|
use rustc_session::lint::builtin::CONST_ITEM_MUTATION;
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
|
|
||||||
pub struct CheckConstItemMutation;
|
pub struct CheckConstItemMutation;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for CheckConstItemMutation {
|
impl<'tcx> MirPass<'tcx> for CheckConstItemMutation {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let mut checker = ConstMutationChecker { body, tcx, target_local: None };
|
let mut checker = ConstMutationChecker { body, tcx, target_local: None };
|
||||||
checker.visit_body(&body);
|
checker.visit_body(&body);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,14 @@ use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_session::lint::builtin::UNALIGNED_REFERENCES;
|
use rustc_session::lint::builtin::UNALIGNED_REFERENCES;
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
|
||||||
pub struct CheckPackedRef;
|
pub struct CheckPackedRef;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for CheckPackedRef {
|
impl<'tcx> MirPass<'tcx> for CheckPackedRef {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let param_env = tcx.param_env(src.instance.def_id());
|
let param_env = tcx.param_env(body.source.def_id());
|
||||||
let source_info = SourceInfo::outermost(body.span);
|
let source_info = SourceInfo::outermost(body.span);
|
||||||
let mut checker = PackedRefChecker { body, tcx, param_env, source_info };
|
let mut checker = PackedRefChecker { body, tcx, param_env, source_info };
|
||||||
checker.visit_body(&body);
|
checker.visit_body(&body);
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
//! [`ForMatchGuard`]: rustc_middle::mir::FakeReadCause::ForMatchGuard
|
//! [`ForMatchGuard`]: rustc_middle::mir::FakeReadCause::ForMatchGuard
|
||||||
//! [`Nop`]: rustc_middle::mir::StatementKind::Nop
|
//! [`Nop`]: rustc_middle::mir::StatementKind::Nop
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_middle::mir::visit::MutVisitor;
|
use rustc_middle::mir::visit::MutVisitor;
|
||||||
use rustc_middle::mir::{Body, BorrowKind, Location, Rvalue};
|
use rustc_middle::mir::{Body, BorrowKind, Location, Rvalue};
|
||||||
use rustc_middle::mir::{Statement, StatementKind};
|
use rustc_middle::mir::{Statement, StatementKind};
|
||||||
|
@ -31,7 +31,7 @@ pub struct DeleteNonCodegenStatements<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements {
|
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>, body: &mut Body<'tcx>) {
|
||||||
let mut delete = DeleteNonCodegenStatements { tcx };
|
let mut delete = DeleteNonCodegenStatements { tcx };
|
||||||
delete.visit_body(body);
|
delete.visit_body(body);
|
||||||
body.user_type_annotations.raw.clear();
|
body.user_type_annotations.raw.clear();
|
||||||
|
|
|
@ -32,7 +32,7 @@ use crate::interpret::{
|
||||||
InterpCx, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand,
|
InterpCx, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand,
|
||||||
PlaceTy, Pointer, ScalarMaybeUninit, StackPopCleanup,
|
PlaceTy, Pointer, ScalarMaybeUninit, StackPopCleanup,
|
||||||
};
|
};
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
|
|
||||||
/// The maximum number of bytes that we'll allocate space for a local or the return value.
|
/// The maximum number of bytes that we'll allocate space for a local or the return value.
|
||||||
/// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just
|
/// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just
|
||||||
|
@ -60,30 +60,31 @@ macro_rules! throw_machine_stop_str {
|
||||||
pub struct ConstProp;
|
pub struct ConstProp;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for 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>, body: &mut Body<'tcx>) {
|
||||||
// will be evaluated by miri and produce its errors there
|
// will be evaluated by miri and produce its errors there
|
||||||
if source.promoted.is_some() {
|
if body.source.promoted.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
use rustc_middle::hir::map::blocks::FnLikeNode;
|
use rustc_middle::hir::map::blocks::FnLikeNode;
|
||||||
let hir_id = tcx.hir().local_def_id_to_hir_id(source.def_id().expect_local());
|
let def_id = body.source.def_id().expect_local();
|
||||||
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
|
|
||||||
let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some();
|
let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some();
|
||||||
let is_assoc_const = tcx.def_kind(source.def_id()) == DefKind::AssocConst;
|
let is_assoc_const = tcx.def_kind(def_id.to_def_id()) == DefKind::AssocConst;
|
||||||
|
|
||||||
// Only run const prop on functions, methods, closures and associated constants
|
// Only run const prop on functions, methods, closures and associated constants
|
||||||
if !is_fn_like && !is_assoc_const {
|
if !is_fn_like && !is_assoc_const {
|
||||||
// skip anon_const/statics/consts because they'll be evaluated by miri anyway
|
// skip anon_const/statics/consts because they'll be evaluated by miri anyway
|
||||||
trace!("ConstProp skipped for {:?}", source.def_id());
|
trace!("ConstProp skipped for {:?}", def_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_generator = tcx.type_of(source.def_id()).is_generator();
|
let is_generator = tcx.type_of(def_id.to_def_id()).is_generator();
|
||||||
// FIXME(welseywiser) const prop doesn't work on generators because of query cycles
|
// FIXME(welseywiser) const prop doesn't work on generators because of query cycles
|
||||||
// computing their layout.
|
// computing their layout.
|
||||||
if is_generator {
|
if is_generator {
|
||||||
trace!("ConstProp skipped for generator {:?}", source.def_id());
|
trace!("ConstProp skipped for generator {:?}", def_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +115,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||||
// the normalization code (leading to cycle errors), since
|
// the normalization code (leading to cycle errors), since
|
||||||
// it's usually never invoked in this way.
|
// it's usually never invoked in this way.
|
||||||
let predicates = tcx
|
let predicates = tcx
|
||||||
.predicates_of(source.def_id())
|
.predicates_of(def_id.to_def_id())
|
||||||
.predicates
|
.predicates
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
||||||
|
@ -122,20 +123,21 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||||
tcx,
|
tcx,
|
||||||
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
|
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
|
||||||
) {
|
) {
|
||||||
trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", source.def_id());
|
trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("ConstProp starting for {:?}", source.def_id());
|
trace!("ConstProp starting for {:?}", def_id);
|
||||||
|
|
||||||
let dummy_body = &Body::new(
|
let dummy_body = &Body::new(
|
||||||
|
body.source,
|
||||||
body.basic_blocks().clone(),
|
body.basic_blocks().clone(),
|
||||||
body.source_scopes.clone(),
|
body.source_scopes.clone(),
|
||||||
body.local_decls.clone(),
|
body.local_decls.clone(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
body.arg_count,
|
body.arg_count,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
tcx.def_span(source.def_id()),
|
tcx.def_span(def_id),
|
||||||
body.generator_kind,
|
body.generator_kind,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -143,10 +145,10 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||||
// constants, instead of just checking for const-folding succeeding.
|
// constants, instead of just checking for const-folding succeeding.
|
||||||
// That would require an uniform one-def no-mutation analysis
|
// That would require an uniform one-def no-mutation analysis
|
||||||
// and RPO (or recursing when needing the value of a local).
|
// and RPO (or recursing when needing the value of a local).
|
||||||
let mut optimization_finder = ConstPropagator::new(body, dummy_body, tcx, source);
|
let mut optimization_finder = ConstPropagator::new(body, dummy_body, tcx);
|
||||||
optimization_finder.visit_body(body);
|
optimization_finder.visit_body(body);
|
||||||
|
|
||||||
trace!("ConstProp done for {:?}", source.def_id());
|
trace!("ConstProp done for {:?}", def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,9 +348,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
dummy_body: &'mir Body<'tcx>,
|
dummy_body: &'mir Body<'tcx>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
) -> ConstPropagator<'mir, 'tcx> {
|
) -> ConstPropagator<'mir, 'tcx> {
|
||||||
let def_id = source.def_id();
|
let def_id = body.source.def_id();
|
||||||
let substs = &InternalSubsts::identity_for_item(tcx, def_id);
|
let substs = &InternalSubsts::identity_for_item(tcx, def_id);
|
||||||
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
//! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
|
//! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
|
||||||
//! future.
|
//! future.
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use crate::util::def_use::DefUseAnalysis;
|
use crate::util::def_use::DefUseAnalysis;
|
||||||
use rustc_middle::mir::visit::MutVisitor;
|
use rustc_middle::mir::visit::MutVisitor;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
|
@ -30,7 +30,7 @@ use rustc_middle::ty::TyCtxt;
|
||||||
pub struct CopyPropagation;
|
pub struct CopyPropagation;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for 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>, body: &mut Body<'tcx>) {
|
||||||
let opts = &tcx.sess.opts.debugging_opts;
|
let opts = &tcx.sess.opts.debugging_opts;
|
||||||
// We only run when the MIR optimization level is > 1.
|
// We only run when the MIR optimization level is > 1.
|
||||||
// This avoids a slow pass, and messing up debug info.
|
// This avoids a slow pass, and messing up debug info.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use crate::util::expand_aggregate;
|
use crate::util::expand_aggregate;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -6,7 +6,7 @@ use rustc_middle::ty::TyCtxt;
|
||||||
pub struct Deaggregator;
|
pub struct Deaggregator;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for Deaggregator {
|
impl<'tcx> MirPass<'tcx> for Deaggregator {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
|
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
|
||||||
let local_decls = &*local_decls;
|
let local_decls = &*local_decls;
|
||||||
for bb in basic_blocks {
|
for bb in basic_blocks {
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
use crate::dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals};
|
use crate::dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals};
|
||||||
use crate::dataflow::Analysis;
|
use crate::dataflow::Analysis;
|
||||||
use crate::{
|
use crate::{
|
||||||
transform::{MirPass, MirSource},
|
transform::MirPass,
|
||||||
util::{dump_mir, PassWhere},
|
util::{dump_mir, PassWhere},
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -126,16 +126,18 @@ const MAX_BLOCKS: usize = 250;
|
||||||
pub struct DestinationPropagation;
|
pub struct DestinationPropagation;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for DestinationPropagation {
|
impl<'tcx> MirPass<'tcx> for DestinationPropagation {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
// Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove
|
// Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove
|
||||||
// storage statements at the moment).
|
// storage statements at the moment).
|
||||||
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
|
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let def_id = body.source.def_id();
|
||||||
|
|
||||||
let candidates = find_candidates(tcx, body);
|
let candidates = find_candidates(tcx, body);
|
||||||
if candidates.is_empty() {
|
if candidates.is_empty() {
|
||||||
debug!("{:?}: no dest prop candidates, done", source.def_id());
|
debug!("{:?}: no dest prop candidates, done", def_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +154,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
|
||||||
let relevant = relevant_locals.count();
|
let relevant = relevant_locals.count();
|
||||||
debug!(
|
debug!(
|
||||||
"{:?}: {} locals ({} relevant), {} blocks",
|
"{:?}: {} locals ({} relevant), {} blocks",
|
||||||
source.def_id(),
|
def_id,
|
||||||
body.local_decls.len(),
|
body.local_decls.len(),
|
||||||
relevant,
|
relevant,
|
||||||
body.basic_blocks().len()
|
body.basic_blocks().len()
|
||||||
|
@ -160,23 +162,21 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
|
||||||
if relevant > MAX_LOCALS {
|
if relevant > MAX_LOCALS {
|
||||||
warn!(
|
warn!(
|
||||||
"too many candidate locals in {:?} ({}, max is {}), not optimizing",
|
"too many candidate locals in {:?} ({}, max is {}), not optimizing",
|
||||||
source.def_id(),
|
def_id, relevant, MAX_LOCALS
|
||||||
relevant,
|
|
||||||
MAX_LOCALS
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if body.basic_blocks().len() > MAX_BLOCKS {
|
if body.basic_blocks().len() > MAX_BLOCKS {
|
||||||
warn!(
|
warn!(
|
||||||
"too many blocks in {:?} ({}, max is {}), not optimizing",
|
"too many blocks in {:?} ({}, max is {}), not optimizing",
|
||||||
source.def_id(),
|
def_id,
|
||||||
body.basic_blocks().len(),
|
body.basic_blocks().len(),
|
||||||
MAX_BLOCKS
|
MAX_BLOCKS
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut conflicts = Conflicts::build(tcx, body, source, &relevant_locals);
|
let mut conflicts = Conflicts::build(tcx, body, &relevant_locals);
|
||||||
|
|
||||||
let mut replacements = Replacements::new(body.local_decls.len());
|
let mut replacements = Replacements::new(body.local_decls.len());
|
||||||
for candidate @ CandidateAssignment { dest, src, loc } in candidates {
|
for candidate @ CandidateAssignment { dest, src, loc } in candidates {
|
||||||
|
@ -192,7 +192,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !tcx.consider_optimizing(|| {
|
if !tcx.consider_optimizing(|| {
|
||||||
format!("DestinationPropagation {:?} {:?}", source.def_id(), candidate)
|
format!("DestinationPropagation {:?} {:?}", def_id, candidate)
|
||||||
}) {
|
}) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -398,7 +398,6 @@ impl Conflicts<'a> {
|
||||||
fn build<'tcx>(
|
fn build<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
body: &'_ Body<'tcx>,
|
body: &'_ Body<'tcx>,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
relevant_locals: &'a BitSet<Local>,
|
relevant_locals: &'a BitSet<Local>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// We don't have to look out for locals that have their address taken, since
|
// We don't have to look out for locals that have their address taken, since
|
||||||
|
@ -409,7 +408,7 @@ impl Conflicts<'a> {
|
||||||
body.local_decls.len(),
|
body.local_decls.len(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let def_id = source.def_id();
|
let def_id = body.source.def_id();
|
||||||
let mut init = MaybeInitializedLocals
|
let mut init = MaybeInitializedLocals
|
||||||
.into_engine(tcx, body, def_id)
|
.into_engine(tcx, body, def_id)
|
||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
|
@ -420,58 +419,49 @@ impl Conflicts<'a> {
|
||||||
.into_results_cursor(body);
|
.into_results_cursor(body);
|
||||||
|
|
||||||
let mut reachable = None;
|
let mut reachable = None;
|
||||||
dump_mir(
|
dump_mir(tcx, None, "DestinationPropagation-dataflow", &"", body, |pass_where, w| {
|
||||||
tcx,
|
let reachable = reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body));
|
||||||
None,
|
|
||||||
"DestinationPropagation-dataflow",
|
|
||||||
&"",
|
|
||||||
source,
|
|
||||||
body,
|
|
||||||
|pass_where, w| {
|
|
||||||
let reachable =
|
|
||||||
reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body));
|
|
||||||
|
|
||||||
match pass_where {
|
match pass_where {
|
||||||
PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => {
|
PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => {
|
||||||
init.seek_before_primary_effect(loc);
|
init.seek_before_primary_effect(loc);
|
||||||
live.seek_after_primary_effect(loc);
|
live.seek_after_primary_effect(loc);
|
||||||
|
|
||||||
writeln!(w, " // init: {:?}", init.get())?;
|
writeln!(w, " // init: {:?}", init.get())?;
|
||||||
writeln!(w, " // live: {:?}", live.get())?;
|
writeln!(w, " // live: {:?}", live.get())?;
|
||||||
}
|
}
|
||||||
PassWhere::AfterTerminator(bb) if reachable.contains(bb) => {
|
PassWhere::AfterTerminator(bb) if reachable.contains(bb) => {
|
||||||
let loc = body.terminator_loc(bb);
|
let loc = body.terminator_loc(bb);
|
||||||
init.seek_after_primary_effect(loc);
|
init.seek_after_primary_effect(loc);
|
||||||
live.seek_before_primary_effect(loc);
|
live.seek_before_primary_effect(loc);
|
||||||
|
|
||||||
writeln!(w, " // init: {:?}", init.get())?;
|
writeln!(w, " // init: {:?}", init.get())?;
|
||||||
writeln!(w, " // live: {:?}", live.get())?;
|
writeln!(w, " // live: {:?}", live.get())?;
|
||||||
}
|
|
||||||
|
|
||||||
PassWhere::BeforeBlock(bb) if reachable.contains(bb) => {
|
|
||||||
init.seek_to_block_start(bb);
|
|
||||||
live.seek_to_block_start(bb);
|
|
||||||
|
|
||||||
writeln!(w, " // init: {:?}", init.get())?;
|
|
||||||
writeln!(w, " // live: {:?}", live.get())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {}
|
|
||||||
|
|
||||||
PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => {
|
|
||||||
writeln!(w, " // init: <unreachable>")?;
|
|
||||||
writeln!(w, " // live: <unreachable>")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
PassWhere::BeforeBlock(_) => {
|
|
||||||
writeln!(w, " // init: <unreachable>")?;
|
|
||||||
writeln!(w, " // live: <unreachable>")?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
PassWhere::BeforeBlock(bb) if reachable.contains(bb) => {
|
||||||
},
|
init.seek_to_block_start(bb);
|
||||||
);
|
live.seek_to_block_start(bb);
|
||||||
|
|
||||||
|
writeln!(w, " // init: {:?}", init.get())?;
|
||||||
|
writeln!(w, " // live: {:?}", live.get())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {}
|
||||||
|
|
||||||
|
PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => {
|
||||||
|
writeln!(w, " // init: <unreachable>")?;
|
||||||
|
writeln!(w, " // live: <unreachable>")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
PassWhere::BeforeBlock(_) => {
|
||||||
|
writeln!(w, " // init: <unreachable>")?;
|
||||||
|
writeln!(w, " // live: <unreachable>")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
relevant_locals,
|
relevant_locals,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::fmt;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use crate::util as mir_util;
|
use crate::util as mir_util;
|
||||||
use rustc_middle::mir::Body;
|
use rustc_middle::mir::Body;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -18,7 +18,7 @@ impl<'tcx> MirPass<'tcx> for Marker {
|
||||||
Cow::Borrowed(self.0)
|
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>, _body: &mut Body<'tcx>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Disambiguator {
|
pub struct Disambiguator {
|
||||||
|
@ -36,17 +36,15 @@ pub fn on_mir_pass<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
pass_num: &dyn fmt::Display,
|
pass_num: &dyn fmt::Display,
|
||||||
pass_name: &str,
|
pass_name: &str,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
is_after: bool,
|
is_after: bool,
|
||||||
) {
|
) {
|
||||||
if mir_util::dump_enabled(tcx, pass_name, source.def_id()) {
|
if mir_util::dump_enabled(tcx, pass_name, body.source.def_id()) {
|
||||||
mir_util::dump_mir(
|
mir_util::dump_mir(
|
||||||
tcx,
|
tcx,
|
||||||
Some(pass_num),
|
Some(pass_num),
|
||||||
pass_name,
|
pass_name,
|
||||||
&Disambiguator { is_after },
|
&Disambiguator { is_after },
|
||||||
source,
|
|
||||||
body,
|
body,
|
||||||
|_, _| Ok(()),
|
|_, _| Ok(()),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use crate::{
|
use crate::{transform::MirPass, util::patch::MirPatch};
|
||||||
transform::{MirPass, MirSource},
|
|
||||||
util::patch::MirPatch,
|
|
||||||
};
|
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{Ty, TyCtxt};
|
use rustc_middle::ty::{Ty, TyCtxt};
|
||||||
use std::{borrow::Cow, fmt::Debug};
|
use std::{borrow::Cow, fmt::Debug};
|
||||||
|
@ -28,11 +25,11 @@ use super::simplify::simplify_cfg;
|
||||||
pub struct EarlyOtherwiseBranch;
|
pub struct EarlyOtherwiseBranch;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
|
impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
if tcx.sess.opts.debugging_opts.mir_opt_level < 1 {
|
if tcx.sess.opts.debugging_opts.mir_opt_level < 1 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
trace!("running EarlyOtherwiseBranch on {:?}", source);
|
trace!("running EarlyOtherwiseBranch on {:?}", body.source);
|
||||||
// we are only interested in this bb if the terminator is a switchInt
|
// we are only interested in this bb if the terminator is a switchInt
|
||||||
let bbs_with_switch =
|
let bbs_with_switch =
|
||||||
body.basic_blocks().iter_enumerated().filter(|(_, bb)| is_switch(bb.terminator()));
|
body.basic_blocks().iter_enumerated().filter(|(_, bb)| is_switch(bb.terminator()));
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::dataflow::on_lookup_result_bits;
|
||||||
use crate::dataflow::MoveDataParamEnv;
|
use crate::dataflow::MoveDataParamEnv;
|
||||||
use crate::dataflow::{on_all_children_bits, on_all_drop_children_bits};
|
use crate::dataflow::{on_all_children_bits, on_all_drop_children_bits};
|
||||||
use crate::dataflow::{Analysis, ResultsCursor};
|
use crate::dataflow::{Analysis, ResultsCursor};
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use crate::util::elaborate_drops::{elaborate_drop, DropFlagState, Unwind};
|
use crate::util::elaborate_drops::{elaborate_drop, DropFlagState, Unwind};
|
||||||
use crate::util::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle};
|
use crate::util::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle};
|
||||||
use crate::util::patch::MirPatch;
|
use crate::util::patch::MirPatch;
|
||||||
|
@ -21,11 +21,11 @@ use std::fmt;
|
||||||
pub struct ElaborateDrops;
|
pub struct ElaborateDrops;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for ElaborateDrops {
|
impl<'tcx> MirPass<'tcx> for ElaborateDrops {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
debug!("elaborate_drops({:?} @ {:?})", src, body.span);
|
debug!("elaborate_drops({:?} @ {:?})", body.source, body.span);
|
||||||
|
|
||||||
let def_id = src.def_id();
|
let def_id = body.source.def_id();
|
||||||
let param_env = tcx.param_env_reveal_all_normalized(src.def_id());
|
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
||||||
let move_data = match MoveData::gather_moves(body, tcx, param_env) {
|
let move_data = match MoveData::gather_moves(body, tcx, param_env) {
|
||||||
Ok(move_data) => move_data,
|
Ok(move_data) => move_data,
|
||||||
Err((move_data, _)) => {
|
Err((move_data, _)) => {
|
||||||
|
|
|
@ -55,7 +55,7 @@ use crate::dataflow::impls::{
|
||||||
use crate::dataflow::{self, Analysis};
|
use crate::dataflow::{self, Analysis};
|
||||||
use crate::transform::no_landing_pads::no_landing_pads;
|
use crate::transform::no_landing_pads::no_landing_pads;
|
||||||
use crate::transform::simplify;
|
use crate::transform::simplify;
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use crate::util::dump_mir;
|
use crate::util::dump_mir;
|
||||||
use crate::util::expand_aggregate;
|
use crate::util::expand_aggregate;
|
||||||
use crate::util::storage;
|
use crate::util::storage;
|
||||||
|
@ -451,11 +451,10 @@ struct LivenessInfo {
|
||||||
fn locals_live_across_suspend_points(
|
fn locals_live_across_suspend_points(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
always_live_locals: &storage::AlwaysLiveLocals,
|
always_live_locals: &storage::AlwaysLiveLocals,
|
||||||
movable: bool,
|
movable: bool,
|
||||||
) -> LivenessInfo {
|
) -> LivenessInfo {
|
||||||
let def_id = source.def_id();
|
let def_id = body.source.def_id();
|
||||||
let body_ref: &Body<'_> = &body;
|
let body_ref: &Body<'_> = &body;
|
||||||
|
|
||||||
// Calculate when MIR locals have live storage. This gives us an upper bound of their
|
// Calculate when MIR locals have live storage. This gives us an upper bound of their
|
||||||
|
@ -915,7 +914,6 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut
|
||||||
fn create_generator_drop_shim<'tcx>(
|
fn create_generator_drop_shim<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
transform: &TransformVisitor<'tcx>,
|
transform: &TransformVisitor<'tcx>,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
gen_ty: Ty<'tcx>,
|
gen_ty: Ty<'tcx>,
|
||||||
body: &mut Body<'tcx>,
|
body: &mut Body<'tcx>,
|
||||||
drop_clean: BasicBlock,
|
drop_clean: BasicBlock,
|
||||||
|
@ -968,7 +966,7 @@ fn create_generator_drop_shim<'tcx>(
|
||||||
// unrelated code from the resume part of the function
|
// unrelated code from the resume part of the function
|
||||||
simplify::remove_dead_blocks(&mut body);
|
simplify::remove_dead_blocks(&mut body);
|
||||||
|
|
||||||
dump_mir(tcx, None, "generator_drop", &0, source, &body, |_, _| Ok(()));
|
dump_mir(tcx, None, "generator_drop", &0, &body, |_, _| Ok(()));
|
||||||
|
|
||||||
body
|
body
|
||||||
}
|
}
|
||||||
|
@ -1070,7 +1068,6 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
|
||||||
fn create_generator_resume_function<'tcx>(
|
fn create_generator_resume_function<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
transform: TransformVisitor<'tcx>,
|
transform: TransformVisitor<'tcx>,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
body: &mut Body<'tcx>,
|
body: &mut Body<'tcx>,
|
||||||
can_return: bool,
|
can_return: bool,
|
||||||
) {
|
) {
|
||||||
|
@ -1142,7 +1139,7 @@ fn create_generator_resume_function<'tcx>(
|
||||||
// unrelated code from the drop part of the function
|
// unrelated code from the drop part of the function
|
||||||
simplify::remove_dead_blocks(body);
|
simplify::remove_dead_blocks(body);
|
||||||
|
|
||||||
dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(()));
|
dump_mir(tcx, None, "generator_resume", &0, body, |_, _| Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
|
fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
|
||||||
|
@ -1239,7 +1236,7 @@ fn create_cases<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for StateTransform {
|
impl<'tcx> MirPass<'tcx> for StateTransform {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let yield_ty = if let Some(yield_ty) = body.yield_ty {
|
let yield_ty = if let Some(yield_ty) = body.yield_ty {
|
||||||
yield_ty
|
yield_ty
|
||||||
} else {
|
} else {
|
||||||
|
@ -1249,7 +1246,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
||||||
|
|
||||||
assert!(body.generator_drop.is_none());
|
assert!(body.generator_drop.is_none());
|
||||||
|
|
||||||
let def_id = source.def_id();
|
let def_id = body.source.def_id();
|
||||||
|
|
||||||
// The first argument is the generator type passed by value
|
// The first argument is the generator type passed by value
|
||||||
let gen_ty = body.local_decls.raw[1].ty;
|
let gen_ty = body.local_decls.raw[1].ty;
|
||||||
|
@ -1307,7 +1304,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
||||||
let always_live_locals = storage::AlwaysLiveLocals::new(&body);
|
let always_live_locals = storage::AlwaysLiveLocals::new(&body);
|
||||||
|
|
||||||
let liveness_info =
|
let liveness_info =
|
||||||
locals_live_across_suspend_points(tcx, body, source, &always_live_locals, movable);
|
locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
|
||||||
|
|
||||||
sanitize_witness(tcx, body, def_id, interior, &upvars, &liveness_info.saved_locals);
|
sanitize_witness(tcx, body, def_id, interior, &upvars, &liveness_info.saved_locals);
|
||||||
|
|
||||||
|
@ -1356,23 +1353,22 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
||||||
// This is expanded to a drop ladder in `elaborate_generator_drops`.
|
// 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);
|
||||||
|
|
||||||
dump_mir(tcx, None, "generator_pre-elab", &0, source, body, |_, _| Ok(()));
|
dump_mir(tcx, None, "generator_pre-elab", &0, body, |_, _| Ok(()));
|
||||||
|
|
||||||
// Expand `drop(generator_struct)` to a drop ladder which destroys upvars.
|
// Expand `drop(generator_struct)` to a drop ladder which destroys upvars.
|
||||||
// If any upvars are moved out of, drop elaboration will handle upvar destruction.
|
// 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`.
|
// 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);
|
||||||
|
|
||||||
dump_mir(tcx, None, "generator_post-transform", &0, source, body, |_, _| Ok(()));
|
dump_mir(tcx, None, "generator_post-transform", &0, body, |_, _| Ok(()));
|
||||||
|
|
||||||
// Create a copy of our MIR and use it to create the drop shim for the generator
|
// Create a copy of our MIR and use it to create the drop shim for the generator
|
||||||
let drop_shim =
|
let drop_shim = create_generator_drop_shim(tcx, &transform, gen_ty, body, drop_clean);
|
||||||
create_generator_drop_shim(tcx, &transform, source, gen_ty, body, drop_clean);
|
|
||||||
|
|
||||||
body.generator_drop = Some(box drop_shim);
|
body.generator_drop = Some(box drop_shim);
|
||||||
|
|
||||||
// Create the Generator::resume function
|
// Create the Generator::resume function
|
||||||
create_generator_resume_function(tcx, transform, source, body, can_return);
|
create_generator_resume_function(tcx, transform, body, can_return);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyC
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use super::simplify::{remove_dead_blocks, CfgSimplifier};
|
use super::simplify::{remove_dead_blocks, CfgSimplifier};
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ struct CallSite<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for Inline {
|
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>, body: &mut Body<'tcx>) {
|
||||||
if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
|
if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
|
||||||
if tcx.sess.opts.debugging_opts.instrument_coverage {
|
if tcx.sess.opts.debugging_opts.instrument_coverage {
|
||||||
// The current implementation of source code coverage injects code region counters
|
// The current implementation of source code coverage injects code region counters
|
||||||
|
@ -45,7 +45,7 @@ impl<'tcx> MirPass<'tcx> for Inline {
|
||||||
// based function.
|
// based function.
|
||||||
debug!("function inlining is disabled when compiling with `instrument_coverage`");
|
debug!("function inlining is disabled when compiling with `instrument_coverage`");
|
||||||
} else {
|
} else {
|
||||||
Inliner { tcx, source, codegen_fn_attrs: tcx.codegen_fn_attrs(source.def_id()) }
|
Inliner { tcx, codegen_fn_attrs: tcx.codegen_fn_attrs(body.source.def_id()) }
|
||||||
.run_pass(body);
|
.run_pass(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,6 @@ impl<'tcx> MirPass<'tcx> for Inline {
|
||||||
|
|
||||||
struct Inliner<'tcx> {
|
struct Inliner<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
codegen_fn_attrs: &'tcx CodegenFnAttrs,
|
codegen_fn_attrs: &'tcx CodegenFnAttrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,11 +73,15 @@ impl Inliner<'tcx> {
|
||||||
|
|
||||||
let mut callsites = VecDeque::new();
|
let mut callsites = VecDeque::new();
|
||||||
|
|
||||||
let param_env = self.tcx.param_env_reveal_all_normalized(self.source.def_id());
|
let def_id = caller_body.source.def_id();
|
||||||
|
|
||||||
|
let param_env = self.tcx.param_env_reveal_all_normalized(def_id);
|
||||||
|
|
||||||
// Only do inlining into fn bodies.
|
// Only do inlining into fn bodies.
|
||||||
let id = self.tcx.hir().local_def_id_to_hir_id(self.source.def_id().expect_local());
|
let self_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
||||||
if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() {
|
if self.tcx.hir().body_owner_kind(self_hir_id).is_fn_or_closure()
|
||||||
|
&& caller_body.source.promoted.is_none()
|
||||||
|
{
|
||||||
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() {
|
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() {
|
||||||
if let Some(callsite) =
|
if let Some(callsite) =
|
||||||
self.get_valid_function_call(bb, bb_data, caller_body, param_env)
|
self.get_valid_function_call(bb, bb_data, caller_body, param_env)
|
||||||
|
@ -104,8 +107,6 @@ impl Inliner<'tcx> {
|
||||||
|
|
||||||
let callee_body = if let Some(callee_def_id) = callsite.callee.as_local() {
|
let callee_body = if let Some(callee_def_id) = callsite.callee.as_local() {
|
||||||
let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
|
let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
|
||||||
let self_hir_id =
|
|
||||||
self.tcx.hir().local_def_id_to_hir_id(self.source.def_id().expect_local());
|
|
||||||
// Avoid a cycle here by only using `optimized_mir` only if we have
|
// Avoid a cycle here by only using `optimized_mir` only if we have
|
||||||
// a lower `HirId` than the callee. This ensures that the callee will
|
// a lower `HirId` than the callee. This ensures that the callee will
|
||||||
// not inline us. This trick only works without incremental compilation.
|
// not inline us. This trick only works without incremental compilation.
|
||||||
|
@ -178,7 +179,7 @@ impl Inliner<'tcx> {
|
||||||
|
|
||||||
// Simplify if we inlined anything.
|
// Simplify if we inlined anything.
|
||||||
if changed {
|
if changed {
|
||||||
debug!("running simplify cfg on {:?}", self.source);
|
debug!("running simplify cfg on {:?}", caller_body.source);
|
||||||
CfgSimplifier::new(caller_body).simplify();
|
CfgSimplifier::new(caller_body).simplify();
|
||||||
remove_dead_blocks(caller_body);
|
remove_dead_blocks(caller_body);
|
||||||
}
|
}
|
||||||
|
@ -300,7 +301,7 @@ impl Inliner<'tcx> {
|
||||||
|
|
||||||
// FIXME: Give a bonus to functions with only a single caller
|
// FIXME: Give a bonus to functions with only a single caller
|
||||||
|
|
||||||
let param_env = tcx.param_env(self.source.def_id());
|
let param_env = tcx.param_env(callee_body.source.def_id());
|
||||||
|
|
||||||
let mut first_block = true;
|
let mut first_block = true;
|
||||||
let mut cost = 0;
|
let mut cost = 0;
|
||||||
|
@ -430,7 +431,7 @@ impl Inliner<'tcx> {
|
||||||
match terminator.kind {
|
match terminator.kind {
|
||||||
// FIXME: Handle inlining of diverging calls
|
// FIXME: Handle inlining of diverging calls
|
||||||
TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
|
TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
|
||||||
debug!("inlined {:?} into {:?}", callsite.callee, self.source);
|
debug!("inlined {:?} into {:?}", callsite.callee, caller_body.source);
|
||||||
|
|
||||||
let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len());
|
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 scope_map = IndexVec::with_capacity(callee_body.source_scopes.len());
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Performs various peephole optimizations.
|
//! Performs various peephole optimizations.
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::Mutability;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
|
@ -19,7 +19,7 @@ use std::mem;
|
||||||
pub struct InstCombine;
|
pub struct InstCombine;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for 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>, body: &mut Body<'tcx>) {
|
||||||
// First, find optimization opportunities. This is done in a pre-pass to keep the MIR
|
// First, find optimization opportunities. This is done in a pre-pass to keep the MIR
|
||||||
// read-only so that we can do global analyses on the MIR in the process (e.g.
|
// read-only so that we can do global analyses on the MIR in the process (e.g.
|
||||||
// `Place::ty()`).
|
// `Place::ty()`).
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use crate::util::pretty;
|
use crate::util::pretty;
|
||||||
use crate::util::spanview::{
|
use crate::util::spanview::{
|
||||||
source_range_no_file, statement_kind_name, terminator_kind_name, write_spanview_document,
|
source_range_no_file, statement_kind_name, terminator_kind_name, write_spanview_document,
|
||||||
|
@ -74,16 +74,11 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
|
impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
|
||||||
fn run_pass(
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) {
|
||||||
&self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
mir_source: MirSource<'tcx>,
|
|
||||||
mir_body: &mut mir::Body<'tcx>,
|
|
||||||
) {
|
|
||||||
// If the InstrumentCoverage pass is called on promoted MIRs, skip them.
|
// If the InstrumentCoverage pass is called on promoted MIRs, skip them.
|
||||||
// See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601
|
// See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601
|
||||||
if mir_source.promoted.is_none() {
|
if mir_body.source.promoted.is_none() {
|
||||||
Instrumentor::new(&self.name(), tcx, mir_source, mir_body).inject_counters();
|
Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +92,6 @@ struct CoverageRegion {
|
||||||
struct Instrumentor<'a, 'tcx> {
|
struct Instrumentor<'a, 'tcx> {
|
||||||
pass_name: &'a str,
|
pass_name: &'a str,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
mir_source: MirSource<'tcx>,
|
|
||||||
mir_body: &'a mut mir::Body<'tcx>,
|
mir_body: &'a mut mir::Body<'tcx>,
|
||||||
hir_body: &'tcx rustc_hir::Body<'tcx>,
|
hir_body: &'tcx rustc_hir::Body<'tcx>,
|
||||||
function_source_hash: Option<u64>,
|
function_source_hash: Option<u64>,
|
||||||
|
@ -106,17 +100,11 @@ struct Instrumentor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
fn new(
|
fn new(pass_name: &'a str, tcx: TyCtxt<'tcx>, mir_body: &'a mut mir::Body<'tcx>) -> Self {
|
||||||
pass_name: &'a str,
|
let hir_body = hir_body(tcx, mir_body.source.def_id());
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
mir_source: MirSource<'tcx>,
|
|
||||||
mir_body: &'a mut mir::Body<'tcx>,
|
|
||||||
) -> Self {
|
|
||||||
let hir_body = hir_body(tcx, mir_source.def_id());
|
|
||||||
Self {
|
Self {
|
||||||
pass_name,
|
pass_name,
|
||||||
tcx,
|
tcx,
|
||||||
mir_source,
|
|
||||||
mir_body,
|
mir_body,
|
||||||
hir_body,
|
hir_body,
|
||||||
function_source_hash: None,
|
function_source_hash: None,
|
||||||
|
@ -156,7 +144,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
|
|
||||||
fn inject_counters(&mut self) {
|
fn inject_counters(&mut self) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let def_id = self.mir_source.def_id();
|
let def_id = self.mir_body.source.def_id();
|
||||||
let mir_body = &self.mir_body;
|
let mir_body = &self.mir_body;
|
||||||
let body_span = self.hir_body.value.span;
|
let body_span = self.hir_body.value.span;
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -239,9 +227,15 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(span_viewables) = span_viewables {
|
if let Some(span_viewables) = span_viewables {
|
||||||
let mut file =
|
let mut file = pretty::create_dump_file(
|
||||||
pretty::create_dump_file(tcx, "html", None, self.pass_name, &0, self.mir_source)
|
tcx,
|
||||||
.expect("Unexpected error creating MIR spanview HTML file");
|
"html",
|
||||||
|
None,
|
||||||
|
self.pass_name,
|
||||||
|
&0,
|
||||||
|
self.mir_body.source,
|
||||||
|
)
|
||||||
|
.expect("Unexpected error creating MIR spanview HTML file");
|
||||||
write_spanview_document(tcx, def_id, span_viewables, &mut file)
|
write_spanview_document(tcx, def_id, span_viewables, &mut file)
|
||||||
.expect("Unexpected IO error dumping coverage spans as HTML");
|
.expect("Unexpected IO error dumping coverage spans as HTML");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ pub struct MatchBranchSimplification;
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
|
impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let param_env = tcx.param_env(src.def_id());
|
let param_env = tcx.param_env(body.source.def_id());
|
||||||
let bbs = body.basic_blocks_mut();
|
let bbs = body.basic_blocks_mut();
|
||||||
'outer: for bb_idx in bbs.indices() {
|
'outer: for bb_idx in bbs.indices() {
|
||||||
let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind {
|
let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use rustc_middle::mir::visit::Visitor as _;
|
||||||
use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
|
use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::steal::Steal;
|
use rustc_middle::ty::steal::Steal;
|
||||||
use rustc_middle::ty::{self, InstanceDef, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ pub mod uninhabited_enum_branching;
|
||||||
pub mod unreachable_prop;
|
pub mod unreachable_prop;
|
||||||
pub mod validate;
|
pub mod validate;
|
||||||
|
|
||||||
|
pub use rustc_middle::mir::MirSource;
|
||||||
|
|
||||||
pub(crate) fn provide(providers: &mut Providers) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
self::check_unsafety::provide(providers);
|
self::check_unsafety::provide(providers);
|
||||||
*providers = Providers {
|
*providers = Providers {
|
||||||
|
@ -132,33 +134,6 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> FxHashSet<LocalDefId> {
|
||||||
set
|
set
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Where a specific `mir::Body` comes from.
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct MirSource<'tcx> {
|
|
||||||
pub instance: InstanceDef<'tcx>,
|
|
||||||
|
|
||||||
/// If `Some`, this is a promoted rvalue within the parent function.
|
|
||||||
pub promoted: Option<Promoted>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> MirSource<'tcx> {
|
|
||||||
pub fn item(def_id: DefId) -> Self {
|
|
||||||
MirSource {
|
|
||||||
instance: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
|
|
||||||
promoted: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
|
|
||||||
self.instance.with_opt_param()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn def_id(&self) -> DefId {
|
|
||||||
self.instance.def_id()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates a default name for the pass based on the name of the
|
/// Generates a default name for the pass based on the name of the
|
||||||
/// type `T`.
|
/// type `T`.
|
||||||
pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
|
pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
|
||||||
|
@ -174,19 +149,16 @@ pub trait MirPass<'tcx> {
|
||||||
default_name::<Self>()
|
default_name::<Self>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>);
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_passes(
|
pub fn run_passes(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
body: &mut Body<'tcx>,
|
body: &mut Body<'tcx>,
|
||||||
instance: InstanceDef<'tcx>,
|
|
||||||
promoted: Option<Promoted>,
|
|
||||||
mir_phase: MirPhase,
|
mir_phase: MirPhase,
|
||||||
passes: &[&[&dyn MirPass<'tcx>]],
|
passes: &[&[&dyn MirPass<'tcx>]],
|
||||||
) {
|
) {
|
||||||
let phase_index = mir_phase.phase_index();
|
let phase_index = mir_phase.phase_index();
|
||||||
let source = MirSource { instance, promoted };
|
|
||||||
let validate = tcx.sess.opts.debugging_opts.validate_mir;
|
let validate = tcx.sess.opts.debugging_opts.validate_mir;
|
||||||
|
|
||||||
if body.phase >= mir_phase {
|
if body.phase >= mir_phase {
|
||||||
|
@ -195,7 +167,7 @@ pub fn run_passes(
|
||||||
|
|
||||||
if validate {
|
if validate {
|
||||||
validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase }
|
validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase }
|
||||||
.run_pass(tcx, source, body);
|
.run_pass(tcx, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
@ -205,13 +177,12 @@ pub fn run_passes(
|
||||||
tcx,
|
tcx,
|
||||||
&format_args!("{:03}-{:03}", phase_index, index),
|
&format_args!("{:03}-{:03}", phase_index, index),
|
||||||
&pass.name(),
|
&pass.name(),
|
||||||
source,
|
|
||||||
body,
|
body,
|
||||||
is_after,
|
is_after,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
run_hooks(body, index, false);
|
run_hooks(body, index, false);
|
||||||
pass.run_pass(tcx, source, body);
|
pass.run_pass(tcx, body);
|
||||||
run_hooks(body, index, true);
|
run_hooks(body, index, true);
|
||||||
|
|
||||||
if validate {
|
if validate {
|
||||||
|
@ -219,7 +190,7 @@ pub fn run_passes(
|
||||||
when: format!("after {} in phase {:?}", pass.name(), mir_phase),
|
when: format!("after {} in phase {:?}", pass.name(), mir_phase),
|
||||||
mir_phase,
|
mir_phase,
|
||||||
}
|
}
|
||||||
.run_pass(tcx, source, body);
|
.run_pass(tcx, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
index += 1;
|
index += 1;
|
||||||
|
@ -235,7 +206,7 @@ pub fn run_passes(
|
||||||
|
|
||||||
if mir_phase == MirPhase::Optimization {
|
if mir_phase == MirPhase::Optimization {
|
||||||
validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase }
|
validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase }
|
||||||
.run_pass(tcx, source, body);
|
.run_pass(tcx, body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,21 +263,11 @@ fn mir_const<'tcx>(
|
||||||
|
|
||||||
let mut body = tcx.mir_built(def).steal();
|
let mut body = tcx.mir_built(def).steal();
|
||||||
|
|
||||||
util::dump_mir(
|
util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
|
||||||
tcx,
|
|
||||||
None,
|
|
||||||
"mir_map",
|
|
||||||
&0,
|
|
||||||
MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None },
|
|
||||||
&body,
|
|
||||||
|_, _| Ok(()),
|
|
||||||
);
|
|
||||||
|
|
||||||
run_passes(
|
run_passes(
|
||||||
tcx,
|
tcx,
|
||||||
&mut body,
|
&mut body,
|
||||||
InstanceDef::Item(def.to_global()),
|
|
||||||
None,
|
|
||||||
MirPhase::Const,
|
MirPhase::Const,
|
||||||
&[&[
|
&[&[
|
||||||
// MIR-level lints.
|
// MIR-level lints.
|
||||||
|
@ -359,14 +320,7 @@ fn mir_promoted(
|
||||||
&[]
|
&[]
|
||||||
};
|
};
|
||||||
|
|
||||||
run_passes(
|
run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]);
|
||||||
tcx,
|
|
||||||
&mut body,
|
|
||||||
InstanceDef::Item(def.to_global()),
|
|
||||||
None,
|
|
||||||
MirPhase::ConstPromotion,
|
|
||||||
&[promote, opt_coverage],
|
|
||||||
);
|
|
||||||
|
|
||||||
let promoted = promote_pass.promoted_fragments.into_inner();
|
let promoted = promote_pass.promoted_fragments.into_inner();
|
||||||
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
|
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
|
||||||
|
@ -391,19 +345,14 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
|
||||||
let (body, _) = tcx.mir_promoted(def);
|
let (body, _) = tcx.mir_promoted(def);
|
||||||
let mut body = body.steal();
|
let mut body = body.steal();
|
||||||
|
|
||||||
run_post_borrowck_cleanup_passes(tcx, &mut body, def.did, None);
|
run_post_borrowck_cleanup_passes(tcx, &mut body);
|
||||||
check_consts::post_drop_elaboration::check_live_drops(tcx, def.did, &body);
|
check_consts::post_drop_elaboration::check_live_drops(tcx, def.did, &body);
|
||||||
tcx.alloc_steal_mir(body)
|
tcx.alloc_steal_mir(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// After this series of passes, no lifetime analysis based on borrowing can be done.
|
/// After this series of passes, no lifetime analysis based on borrowing can be done.
|
||||||
fn run_post_borrowck_cleanup_passes<'tcx>(
|
fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
tcx: TyCtxt<'tcx>,
|
debug!("post_borrowck_cleanup({:?})", body.source.def_id());
|
||||||
body: &mut Body<'tcx>,
|
|
||||||
def_id: LocalDefId,
|
|
||||||
promoted: Option<Promoted>,
|
|
||||||
) {
|
|
||||||
debug!("post_borrowck_cleanup({:?})", def_id);
|
|
||||||
|
|
||||||
let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[
|
let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[
|
||||||
// Remove all things only needed by analysis
|
// Remove all things only needed by analysis
|
||||||
|
@ -428,22 +377,10 @@ fn run_post_borrowck_cleanup_passes<'tcx>(
|
||||||
&deaggregator::Deaggregator,
|
&deaggregator::Deaggregator,
|
||||||
];
|
];
|
||||||
|
|
||||||
run_passes(
|
run_passes(tcx, body, MirPhase::DropLowering, &[post_borrowck_cleanup]);
|
||||||
tcx,
|
|
||||||
body,
|
|
||||||
InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())),
|
|
||||||
promoted,
|
|
||||||
MirPhase::DropLowering,
|
|
||||||
&[post_borrowck_cleanup],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_optimization_passes<'tcx>(
|
fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
body: &mut Body<'tcx>,
|
|
||||||
def_id: LocalDefId,
|
|
||||||
promoted: Option<Promoted>,
|
|
||||||
) {
|
|
||||||
let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level;
|
let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level;
|
||||||
|
|
||||||
// Lowering generator control-flow and variables has to happen before we do anything else
|
// Lowering generator control-flow and variables has to happen before we do anything else
|
||||||
|
@ -502,8 +439,6 @@ fn run_optimization_passes<'tcx>(
|
||||||
run_passes(
|
run_passes(
|
||||||
tcx,
|
tcx,
|
||||||
body,
|
body,
|
||||||
InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())),
|
|
||||||
promoted,
|
|
||||||
MirPhase::GeneratorLowering,
|
MirPhase::GeneratorLowering,
|
||||||
&[
|
&[
|
||||||
if mir_opt_level > 0 {
|
if mir_opt_level > 0 {
|
||||||
|
@ -519,8 +454,6 @@ fn run_optimization_passes<'tcx>(
|
||||||
run_passes(
|
run_passes(
|
||||||
tcx,
|
tcx,
|
||||||
body,
|
body,
|
||||||
InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())),
|
|
||||||
promoted,
|
|
||||||
MirPhase::Optimization,
|
MirPhase::Optimization,
|
||||||
&[
|
&[
|
||||||
if mir_opt_level > 0 { optimizations } else { no_optimizations },
|
if mir_opt_level > 0 { optimizations } else { no_optimizations },
|
||||||
|
@ -558,7 +491,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal();
|
let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal();
|
||||||
run_optimization_passes(tcx, &mut body, def.did, None);
|
run_optimization_passes(tcx, &mut body);
|
||||||
|
|
||||||
debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
|
debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
|
||||||
|
|
||||||
|
@ -581,9 +514,9 @@ fn promoted_mir<'tcx>(
|
||||||
let (_, promoted) = tcx.mir_promoted(def);
|
let (_, promoted) = tcx.mir_promoted(def);
|
||||||
let mut promoted = promoted.steal();
|
let mut promoted = promoted.steal();
|
||||||
|
|
||||||
for (p, mut body) in promoted.iter_enumerated_mut() {
|
for body in &mut promoted {
|
||||||
run_post_borrowck_cleanup_passes(tcx, &mut body, def.did, Some(p));
|
run_post_borrowck_cleanup_passes(tcx, body);
|
||||||
run_optimization_passes(tcx, &mut body, def.did, Some(p));
|
run_optimization_passes(tcx, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
|
debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! This pass removes jumps to basic blocks containing only a return, and replaces them with a
|
//! This pass removes jumps to basic blocks containing only a return, and replaces them with a
|
||||||
//! return instead.
|
//! return instead.
|
||||||
|
|
||||||
use crate::transform::{simplify, MirPass, MirSource};
|
use crate::transform::{simplify, MirPass};
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -9,7 +9,7 @@ use rustc_middle::ty::TyCtxt;
|
||||||
pub struct MultipleReturnTerminators;
|
pub struct MultipleReturnTerminators;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators {
|
impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
if tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
|
if tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! This pass removes the unwind branch of all the terminators when the no-landing-pads option is
|
//! This pass removes the unwind branch of all the terminators when the no-landing-pads option is
|
||||||
//! specified.
|
//! specified.
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_middle::mir::visit::MutVisitor;
|
use rustc_middle::mir::visit::MutVisitor;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -18,7 +18,7 @@ impl<'tcx> NoLandingPads<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for 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>, body: &mut Body<'tcx>) {
|
||||||
no_landing_pads(tcx, body)
|
no_landing_pads(tcx, body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor}
|
||||||
use rustc_middle::mir::{self, BasicBlock, Local, Location};
|
use rustc_middle::mir::{self, BasicBlock, Local, Location};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
|
|
||||||
/// This pass looks for MIR that always copies the same local into the return place and eliminates
|
/// This pass looks for MIR that always copies the same local into the return place and eliminates
|
||||||
/// the copy by renaming all uses of that local to `_0`.
|
/// the copy by renaming all uses of that local to `_0`.
|
||||||
|
@ -31,7 +31,7 @@ use crate::transform::{MirPass, MirSource};
|
||||||
pub struct RenameReturnPlace;
|
pub struct RenameReturnPlace;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
|
impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut mir::Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
|
||||||
if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
|
if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -39,14 +39,14 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
|
||||||
let returned_local = match local_eligible_for_nrvo(body) {
|
let returned_local = match local_eligible_for_nrvo(body) {
|
||||||
Some(l) => l,
|
Some(l) => l,
|
||||||
None => {
|
None => {
|
||||||
debug!("`{:?}` was ineligible for NRVO", src.def_id());
|
debug!("`{:?}` was ineligible for NRVO", body.source.def_id());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"`{:?}` was eligible for NRVO, making {:?} the return place",
|
"`{:?}` was eligible for NRVO, making {:?} the return place",
|
||||||
src.def_id(),
|
body.source.def_id(),
|
||||||
returned_local
|
returned_local
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ use std::{cmp, iter, mem};
|
||||||
|
|
||||||
use crate::const_eval::{is_const_fn, is_unstable_const_fn};
|
use crate::const_eval::{is_const_fn, is_unstable_const_fn};
|
||||||
use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstCx};
|
use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstCx};
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
|
|
||||||
/// A `MirPass` for promotion.
|
/// A `MirPass` for promotion.
|
||||||
///
|
///
|
||||||
|
@ -47,7 +47,7 @@ pub struct PromoteTemps<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
|
impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
// There's not really any point in promoting errorful MIR.
|
// There's not really any point in promoting errorful MIR.
|
||||||
//
|
//
|
||||||
// This does not include MIR that failed const-checking, which we still try to promote.
|
// This does not include MIR that failed const-checking, which we still try to promote.
|
||||||
|
@ -56,11 +56,11 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if src.promoted.is_some() {
|
if body.source.promoted.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let def = src.with_opt_param().expect_local();
|
let def = body.source.with_opt_param().expect_local();
|
||||||
|
|
||||||
let mut rpo = traversal::reverse_postorder(body);
|
let mut rpo = traversal::reverse_postorder(body);
|
||||||
let ccx = ConstCx::new(tcx, def.did, body);
|
let ccx = ConstCx::new(tcx, def.did, body);
|
||||||
|
@ -1167,6 +1167,7 @@ pub fn promote_candidates<'tcx>(
|
||||||
let initial_locals = iter::once(LocalDecl::new(tcx.types.never, body.span)).collect();
|
let initial_locals = iter::once(LocalDecl::new(tcx.types.never, body.span)).collect();
|
||||||
|
|
||||||
let mut promoted = Body::new(
|
let mut promoted = Body::new(
|
||||||
|
body.source, // `promoted` gets filled in below
|
||||||
IndexVec::new(),
|
IndexVec::new(),
|
||||||
// FIXME: maybe try to filter this to avoid blowing up
|
// FIXME: maybe try to filter this to avoid blowing up
|
||||||
// memory usage?
|
// memory usage?
|
||||||
|
@ -1190,7 +1191,8 @@ pub fn promote_candidates<'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
//FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice
|
//FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice
|
||||||
if let Some(promoted) = promoter.promote_candidate(def, candidate, promotions.len()) {
|
if let Some(mut promoted) = promoter.promote_candidate(def, candidate, promotions.len()) {
|
||||||
|
promoted.source.promoted = Some(promotions.next_index());
|
||||||
promotions.push(promoted);
|
promotions.push(promoted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use crate::util::patch::MirPatch;
|
use crate::util::patch::MirPatch;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
|
@ -20,7 +20,7 @@ pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
|
impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
remove_noop_landing_pads(tcx, body);
|
remove_noop_landing_pads(tcx, body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! This pass replaces a drop of a type that does not need dropping, with a goto
|
//! This pass replaces a drop of a type that does not need dropping, with a goto
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_middle::mir::visit::Visitor;
|
use rustc_middle::mir::visit::Visitor;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
|
@ -11,13 +11,13 @@ use super::simplify::simplify_cfg;
|
||||||
pub struct RemoveUnneededDrops;
|
pub struct RemoveUnneededDrops;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
|
impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
trace!("Running RemoveUnneededDrops on {:?}", source);
|
trace!("Running RemoveUnneededDrops on {:?}", body.source);
|
||||||
let mut opt_finder = RemoveUnneededDropsOptimizationFinder {
|
let mut opt_finder = RemoveUnneededDropsOptimizationFinder {
|
||||||
tcx,
|
tcx,
|
||||||
body,
|
body,
|
||||||
optimizations: vec![],
|
optimizations: vec![],
|
||||||
def_id: source.def_id().expect_local(),
|
def_id: body.source.def_id().expect_local(),
|
||||||
};
|
};
|
||||||
opt_finder.visit_body(body);
|
opt_finder.visit_body(body);
|
||||||
let should_simplify = !opt_finder.optimizations.is_empty();
|
let should_simplify = !opt_finder.optimizations.is_empty();
|
||||||
|
|
|
@ -5,7 +5,7 @@ use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::mir::{self, Body, Local, Location};
|
use rustc_middle::mir::{self, Body, Local, Location};
|
||||||
|
@ -23,9 +23,9 @@ use crate::dataflow::{Analysis, JoinSemiLattice, Results, ResultsCursor};
|
||||||
pub struct SanityCheck;
|
pub struct SanityCheck;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for 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>, body: &mut Body<'tcx>) {
|
||||||
use crate::dataflow::has_rustc_mir_with;
|
use crate::dataflow::has_rustc_mir_with;
|
||||||
let def_id = src.def_id();
|
let def_id = body.source.def_id();
|
||||||
if !tcx.has_attr(def_id, sym::rustc_mir) {
|
if !tcx.has_attr(def_id, sym::rustc_mir) {
|
||||||
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
|
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
|
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
|
||||||
//! return.
|
//! return.
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
||||||
|
@ -59,7 +59,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg {
|
||||||
Cow::Borrowed(&self.label)
|
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>, body: &mut Body<'tcx>) {
|
||||||
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body);
|
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body);
|
||||||
simplify_cfg(body);
|
simplify_cfg(body);
|
||||||
}
|
}
|
||||||
|
@ -318,8 +318,8 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) {
|
||||||
pub struct SimplifyLocals;
|
pub struct SimplifyLocals;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for 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>, body: &mut Body<'tcx>) {
|
||||||
trace!("running SimplifyLocals on {:?}", source);
|
trace!("running SimplifyLocals on {:?}", body.source);
|
||||||
|
|
||||||
// First, we're going to get a count of *actual* uses for every `Local`.
|
// First, we're going to get a count of *actual* uses for every `Local`.
|
||||||
// Take a look at `DeclMarker::visit_local()` to see exactly what is ignored.
|
// Take a look at `DeclMarker::visit_local()` to see exactly what is ignored.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! A pass that simplifies branches when their condition is known.
|
//! A pass that simplifies branches when their condition is known.
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches {
|
||||||
Cow::Borrowed(&self.label)
|
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>, body: &mut Body<'tcx>) {
|
||||||
let param_env = tcx.param_env(src.def_id());
|
let param_env = tcx.param_env(body.source.def_id());
|
||||||
for block in body.basic_blocks_mut() {
|
for block in body.basic_blocks_mut() {
|
||||||
let terminator = block.terminator_mut();
|
let terminator = block.terminator_mut();
|
||||||
terminator.kind = match terminator.kind {
|
terminator.kind = match terminator.kind {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{MirPass, MirSource};
|
use super::MirPass;
|
||||||
use rustc_middle::{
|
use rustc_middle::{
|
||||||
mir::{
|
mir::{
|
||||||
interpret::Scalar, BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement,
|
interpret::Scalar, BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement,
|
||||||
|
@ -24,8 +24,8 @@ use rustc_middle::{
|
||||||
pub struct SimplifyComparisonIntegral;
|
pub struct SimplifyComparisonIntegral;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral {
|
impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral {
|
||||||
fn run_pass(&self, _: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
trace!("Running SimplifyComparisonIntegral on {:?}", source);
|
trace!("Running SimplifyComparisonIntegral on {:?}", body.source);
|
||||||
|
|
||||||
let helper = OptimizationFinder { body };
|
let helper = OptimizationFinder { body };
|
||||||
let opts = helper.find_optimizations();
|
let opts = helper.find_optimizations();
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
//!
|
//!
|
||||||
//! into just `x`.
|
//! into just `x`.
|
||||||
|
|
||||||
use crate::transform::{simplify, MirPass, MirSource};
|
use crate::transform::{simplify, MirPass};
|
||||||
use itertools::Itertools as _;
|
use itertools::Itertools as _;
|
||||||
use rustc_index::{bit_set::BitSet, vec::IndexVec};
|
use rustc_index::{bit_set::BitSet, vec::IndexVec};
|
||||||
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
|
||||||
|
@ -367,13 +367,15 @@ fn optimization_applies<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
|
impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
// FIXME(77359): This optimization can result in unsoundness.
|
// FIXME(77359): This optimization can result in unsoundness.
|
||||||
if !tcx.sess.opts.debugging_opts.unsound_mir_opts {
|
if !tcx.sess.opts.debugging_opts.unsound_mir_opts {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let source = body.source;
|
||||||
trace!("running SimplifyArmIdentity on {:?}", source);
|
trace!("running SimplifyArmIdentity on {:?}", source);
|
||||||
|
|
||||||
let local_uses = LocalUseCounter::get_local_uses(body);
|
let local_uses = LocalUseCounter::get_local_uses(body);
|
||||||
let (basic_blocks, local_decls, debug_info) =
|
let (basic_blocks, local_decls, debug_info) =
|
||||||
body.basic_blocks_local_decls_mut_and_var_debug_info();
|
body.basic_blocks_local_decls_mut_and_var_debug_info();
|
||||||
|
@ -528,8 +530,8 @@ fn match_variant_field_place<'tcx>(place: Place<'tcx>) -> Option<(Local, VarFiel
|
||||||
pub struct SimplifyBranchSame;
|
pub struct SimplifyBranchSame;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
|
impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
trace!("Running SimplifyBranchSame on {:?}", source);
|
trace!("Running SimplifyBranchSame on {:?}", body.source);
|
||||||
let finder = SimplifyBranchSameOptimizationFinder { body, tcx };
|
let finder = SimplifyBranchSameOptimizationFinder { body, tcx };
|
||||||
let opts = finder.find();
|
let opts = finder.find();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! A pass that eliminates branches on uninhabited enum variants.
|
//! A pass that eliminates branches on uninhabited enum variants.
|
||||||
|
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind,
|
BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind,
|
||||||
};
|
};
|
||||||
|
@ -66,12 +66,12 @@ fn variant_discriminants<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
if source.promoted.is_some() {
|
if body.source.promoted.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("UninhabitedEnumBranching starting for {:?}", source);
|
trace!("UninhabitedEnumBranching starting for {:?}", body.source);
|
||||||
|
|
||||||
let basic_block_count = body.basic_blocks().len();
|
let basic_block_count = body.basic_blocks().len();
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let layout = tcx.layout_of(tcx.param_env(source.def_id()).and(discriminant_ty));
|
let layout = tcx.layout_of(tcx.param_env(body.source.def_id()).and(discriminant_ty));
|
||||||
|
|
||||||
let allowed_variants = if let Ok(layout) = layout {
|
let allowed_variants = if let Ok(layout) = layout {
|
||||||
variant_discriminants(&layout, discriminant_ty, tcx)
|
variant_discriminants(&layout, discriminant_ty, tcx)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//! post-order traversal of the blocks.
|
//! post-order traversal of the blocks.
|
||||||
|
|
||||||
use crate::transform::simplify;
|
use crate::transform::simplify;
|
||||||
use crate::transform::{MirPass, MirSource};
|
use crate::transform::MirPass;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -12,7 +12,7 @@ use std::borrow::Cow;
|
||||||
pub struct UnreachablePropagation;
|
pub struct UnreachablePropagation;
|
||||||
|
|
||||||
impl MirPass<'_> for UnreachablePropagation {
|
impl MirPass<'_> for UnreachablePropagation {
|
||||||
fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
if tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
|
if tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
|
||||||
// Enable only under -Zmir-opt-level=3 as in some cases (check the deeply-nested-opt
|
// Enable only under -Zmir-opt-level=3 as in some cases (check the deeply-nested-opt
|
||||||
// perf benchmark) LLVM may spend quite a lot of time optimizing the generated code.
|
// perf benchmark) LLVM may spend quite a lot of time optimizing the generated code.
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::dataflow::impls::MaybeStorageLive;
|
||||||
use crate::dataflow::{Analysis, ResultsCursor};
|
use crate::dataflow::{Analysis, ResultsCursor};
|
||||||
use crate::util::storage::AlwaysLiveLocals;
|
use crate::util::storage::AlwaysLiveLocals;
|
||||||
|
|
||||||
use super::{MirPass, MirSource};
|
use super::MirPass;
|
||||||
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, Rvalue,
|
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, Rvalue,
|
||||||
|
@ -31,8 +31,8 @@ pub struct Validator {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for Validator {
|
impl<'tcx> MirPass<'tcx> for Validator {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let def_id = source.def_id();
|
let def_id = body.source.def_id();
|
||||||
let param_env = tcx.param_env(def_id);
|
let param_env = tcx.param_env(def_id);
|
||||||
let mir_phase = self.mir_phase;
|
let mir_phase = self.mir_phase;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(body);
|
.into_results_cursor(body);
|
||||||
|
|
||||||
TypeChecker { when: &self.when, source, body, tcx, param_env, mir_phase, storage_liveness }
|
TypeChecker { when: &self.when, body, tcx, param_env, mir_phase, storage_liveness }
|
||||||
.visit_body(body);
|
.visit_body(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,6 @@ pub fn equal_up_to_regions(
|
||||||
|
|
||||||
struct TypeChecker<'a, 'tcx> {
|
struct TypeChecker<'a, 'tcx> {
|
||||||
when: &'a str,
|
when: &'a str,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
body: &'a Body<'tcx>,
|
body: &'a Body<'tcx>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
|
@ -158,7 +157,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
span,
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
"broken MIR in {:?} ({}) at {:?}:\n{}",
|
"broken MIR in {:?} ({}) at {:?}:\n{}",
|
||||||
self.source.instance,
|
self.body.source.instance,
|
||||||
self.when,
|
self.when,
|
||||||
location,
|
location,
|
||||||
msg.as_ref()
|
msg.as_ref()
|
||||||
|
|
|
@ -22,7 +22,7 @@ where
|
||||||
|
|
||||||
for def_id in def_ids {
|
for def_id in def_ids {
|
||||||
let body = &tcx.optimized_mir(def_id);
|
let body = &tcx.optimized_mir(def_id);
|
||||||
write_mir_fn_graphviz(tcx, def_id, body, use_subgraphs, w)?;
|
write_mir_fn_graphviz(tcx, body, use_subgraphs, w)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if use_subgraphs {
|
if use_subgraphs {
|
||||||
|
@ -41,7 +41,6 @@ pub fn graphviz_safe_def_name(def_id: DefId) -> String {
|
||||||
/// Write a graphviz DOT graph of the MIR.
|
/// Write a graphviz DOT graph of the MIR.
|
||||||
pub fn write_mir_fn_graphviz<'tcx, W>(
|
pub fn write_mir_fn_graphviz<'tcx, W>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: DefId,
|
|
||||||
body: &Body<'_>,
|
body: &Body<'_>,
|
||||||
subgraph: bool,
|
subgraph: bool,
|
||||||
w: &mut W,
|
w: &mut W,
|
||||||
|
@ -49,6 +48,7 @@ pub fn write_mir_fn_graphviz<'tcx, W>(
|
||||||
where
|
where
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
|
let def_id = body.source.def_id();
|
||||||
let kind = if subgraph { "subgraph" } else { "digraph" };
|
let kind = if subgraph { "subgraph" } else { "digraph" };
|
||||||
let cluster = if subgraph { "cluster_" } else { "" }; // Prints a border around MIR
|
let cluster = if subgraph { "cluster_" } else { "" }; // Prints a border around MIR
|
||||||
let def_name = graphviz_safe_def_name(def_id);
|
let def_name = graphviz_safe_def_name(def_id);
|
||||||
|
|
|
@ -75,17 +75,16 @@ pub fn dump_mir<'tcx, F>(
|
||||||
pass_num: Option<&dyn Display>,
|
pass_num: Option<&dyn Display>,
|
||||||
pass_name: &str,
|
pass_name: &str,
|
||||||
disambiguator: &dyn Display,
|
disambiguator: &dyn Display,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
extra_data: F,
|
extra_data: F,
|
||||||
) where
|
) where
|
||||||
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
|
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
|
||||||
{
|
{
|
||||||
if !dump_enabled(tcx, pass_name, source.def_id()) {
|
if !dump_enabled(tcx, pass_name, body.source.def_id()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, source, body, extra_data);
|
dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, body, extra_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) -> bool {
|
pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) -> bool {
|
||||||
|
@ -113,20 +112,20 @@ fn dump_matched_mir_node<'tcx, F>(
|
||||||
pass_num: Option<&dyn Display>,
|
pass_num: Option<&dyn Display>,
|
||||||
pass_name: &str,
|
pass_name: &str,
|
||||||
disambiguator: &dyn Display,
|
disambiguator: &dyn Display,
|
||||||
source: MirSource<'tcx>,
|
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
mut extra_data: F,
|
mut extra_data: F,
|
||||||
) where
|
) where
|
||||||
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
|
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
|
||||||
{
|
{
|
||||||
let _: io::Result<()> = try {
|
let _: io::Result<()> = try {
|
||||||
let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?;
|
let mut file =
|
||||||
|
create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body.source)?;
|
||||||
let def_path = ty::print::with_forced_impl_filename_line(|| {
|
let def_path = ty::print::with_forced_impl_filename_line(|| {
|
||||||
// see notes on #41697 above
|
// see notes on #41697 above
|
||||||
tcx.def_path_str(source.def_id())
|
tcx.def_path_str(body.source.def_id())
|
||||||
});
|
});
|
||||||
write!(file, "// MIR for `{}", def_path)?;
|
write!(file, "// MIR for `{}", def_path)?;
|
||||||
match source.promoted {
|
match body.source.promoted {
|
||||||
None => write!(file, "`")?,
|
None => write!(file, "`")?,
|
||||||
Some(promoted) => write!(file, "::{:?}`", promoted)?,
|
Some(promoted) => write!(file, "::{:?}`", promoted)?,
|
||||||
}
|
}
|
||||||
|
@ -137,24 +136,24 @@ fn dump_matched_mir_node<'tcx, F>(
|
||||||
writeln!(file)?;
|
writeln!(file)?;
|
||||||
extra_data(PassWhere::BeforeCFG, &mut file)?;
|
extra_data(PassWhere::BeforeCFG, &mut file)?;
|
||||||
write_user_type_annotations(tcx, body, &mut file)?;
|
write_user_type_annotations(tcx, body, &mut file)?;
|
||||||
write_mir_fn(tcx, source, body, &mut extra_data, &mut file)?;
|
write_mir_fn(tcx, body, &mut extra_data, &mut file)?;
|
||||||
extra_data(PassWhere::AfterCFG, &mut file)?;
|
extra_data(PassWhere::AfterCFG, &mut file)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
if tcx.sess.opts.debugging_opts.dump_mir_graphviz {
|
if tcx.sess.opts.debugging_opts.dump_mir_graphviz {
|
||||||
let _: io::Result<()> = try {
|
let _: io::Result<()> = try {
|
||||||
let mut file =
|
let mut file =
|
||||||
create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?;
|
create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, body.source)?;
|
||||||
write_mir_fn_graphviz(tcx, source.def_id(), body, false, &mut file)?;
|
write_mir_fn_graphviz(tcx, body, false, &mut file)?;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(spanview) = tcx.sess.opts.debugging_opts.dump_mir_spanview {
|
if let Some(spanview) = tcx.sess.opts.debugging_opts.dump_mir_spanview {
|
||||||
let _: io::Result<()> = try {
|
let _: io::Result<()> = try {
|
||||||
let mut file =
|
let mut file =
|
||||||
create_dump_file(tcx, "html", pass_num, pass_name, disambiguator, source)?;
|
create_dump_file(tcx, "html", pass_num, pass_name, disambiguator, body.source)?;
|
||||||
if source.def_id().is_local() {
|
if body.source.def_id().is_local() {
|
||||||
write_mir_fn_spanview(tcx, source.def_id(), body, spanview, &mut file)?;
|
write_mir_fn_spanview(tcx, body.source.def_id(), body, spanview, &mut file)?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -263,15 +262,11 @@ pub fn write_mir_pretty<'tcx>(
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_mir_fn(tcx, MirSource::item(def_id), body, &mut |_, _| Ok(()), w)?;
|
write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?;
|
||||||
|
|
||||||
for (i, body) in tcx.promoted_mir(def_id).iter_enumerated() {
|
for body in tcx.promoted_mir(def_id) {
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
let src = MirSource {
|
write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?;
|
||||||
instance: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
|
|
||||||
promoted: Some(i),
|
|
||||||
};
|
|
||||||
write_mir_fn(tcx, src, body, &mut |_, _| Ok(()), w)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -280,7 +275,6 @@ pub fn write_mir_pretty<'tcx>(
|
||||||
/// Write out a human-readable textual representation for the given function.
|
/// Write out a human-readable textual representation for the given function.
|
||||||
pub fn write_mir_fn<'tcx, F>(
|
pub fn write_mir_fn<'tcx, F>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
src: MirSource<'tcx>,
|
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
extra_data: &mut F,
|
extra_data: &mut F,
|
||||||
w: &mut dyn Write,
|
w: &mut dyn Write,
|
||||||
|
@ -288,7 +282,7 @@ pub fn write_mir_fn<'tcx, F>(
|
||||||
where
|
where
|
||||||
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
|
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
|
||||||
{
|
{
|
||||||
write_mir_intro(tcx, src, body, w)?;
|
write_mir_intro(tcx, body, w)?;
|
||||||
for block in body.basic_blocks().indices() {
|
for block in body.basic_blocks().indices() {
|
||||||
extra_data(PassWhere::BeforeBlock(block), w)?;
|
extra_data(PassWhere::BeforeBlock(block), w)?;
|
||||||
write_basic_block(tcx, block, body, extra_data, w)?;
|
write_basic_block(tcx, block, body, extra_data, w)?;
|
||||||
|
@ -548,11 +542,10 @@ fn write_scope_tree(
|
||||||
/// local variables (both user-defined bindings and compiler temporaries).
|
/// local variables (both user-defined bindings and compiler temporaries).
|
||||||
pub fn write_mir_intro<'tcx>(
|
pub fn write_mir_intro<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
src: MirSource<'tcx>,
|
|
||||||
body: &Body<'_>,
|
body: &Body<'_>,
|
||||||
w: &mut dyn Write,
|
w: &mut dyn Write,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
write_mir_sig(tcx, src, body, w)?;
|
write_mir_sig(tcx, body, w)?;
|
||||||
writeln!(w, "{{")?;
|
writeln!(w, "{{")?;
|
||||||
|
|
||||||
// construct a scope tree and write it out
|
// construct a scope tree and write it out
|
||||||
|
@ -850,25 +843,21 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_mir_sig(
|
fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Result<()> {
|
||||||
tcx: TyCtxt<'_>,
|
|
||||||
src: MirSource<'tcx>,
|
|
||||||
body: &Body<'_>,
|
|
||||||
w: &mut dyn Write,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
|
|
||||||
trace!("write_mir_sig: {:?}", src.instance);
|
trace!("write_mir_sig: {:?}", body.source.instance);
|
||||||
let kind = tcx.def_kind(src.def_id());
|
let def_id = body.source.def_id();
|
||||||
|
let kind = tcx.def_kind(def_id);
|
||||||
let is_function = match kind {
|
let is_function = match kind {
|
||||||
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true,
|
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true,
|
||||||
_ => tcx.is_closure(src.def_id()),
|
_ => tcx.is_closure(def_id),
|
||||||
};
|
};
|
||||||
match (kind, src.promoted) {
|
match (kind, body.source.promoted) {
|
||||||
(_, Some(i)) => write!(w, "{:?} in ", i)?,
|
(_, Some(i)) => write!(w, "{:?} in ", i)?,
|
||||||
(DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
|
(DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
|
||||||
(DefKind::Static, _) => {
|
(DefKind::Static, _) => {
|
||||||
write!(w, "static {}", if tcx.is_mutable_static(src.def_id()) { "mut " } else { "" })?
|
write!(w, "static {}", if tcx.is_mutable_static(def_id) { "mut " } else { "" })?
|
||||||
}
|
}
|
||||||
(_, _) if is_function => write!(w, "fn ")?,
|
(_, _) if is_function => write!(w, "fn ")?,
|
||||||
(DefKind::AnonConst, _) => {} // things like anon const, not an item
|
(DefKind::AnonConst, _) => {} // things like anon const, not an item
|
||||||
|
@ -877,10 +866,10 @@ fn write_mir_sig(
|
||||||
|
|
||||||
ty::print::with_forced_impl_filename_line(|| {
|
ty::print::with_forced_impl_filename_line(|| {
|
||||||
// see notes on #41697 elsewhere
|
// see notes on #41697 elsewhere
|
||||||
write!(w, "{}", tcx.def_path_str(src.def_id()))
|
write!(w, "{}", tcx.def_path_str(def_id))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if src.promoted.is_none() && is_function {
|
if body.source.promoted.is_none() && is_function {
|
||||||
write!(w, "(")?;
|
write!(w, "(")?;
|
||||||
|
|
||||||
// fn argument types.
|
// fn argument types.
|
||||||
|
|
|
@ -29,7 +29,13 @@ crate fn mir_built<'tcx>(
|
||||||
return tcx.mir_built(def);
|
return tcx.mir_built(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcx.alloc_steal_mir(mir_build(tcx, def))
|
let mut body = mir_build(tcx, def);
|
||||||
|
if def.const_param_did.is_some() {
|
||||||
|
assert!(matches!(body.source.instance, ty::InstanceDef::Item(_)));
|
||||||
|
body.source = MirSource::from_instance(ty::InstanceDef::Item(def.to_global()));
|
||||||
|
}
|
||||||
|
|
||||||
|
tcx.alloc_steal_mir(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct the MIR for a given `DefId`.
|
/// Construct the MIR for a given `DefId`.
|
||||||
|
@ -296,6 +302,7 @@ struct Builder<'a, 'tcx> {
|
||||||
hir: Cx<'a, 'tcx>,
|
hir: Cx<'a, 'tcx>,
|
||||||
cfg: CFG<'tcx>,
|
cfg: CFG<'tcx>,
|
||||||
|
|
||||||
|
def_id: DefId,
|
||||||
fn_span: Span,
|
fn_span: Span,
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
generator_kind: Option<GeneratorKind>,
|
generator_kind: Option<GeneratorKind>,
|
||||||
|
@ -597,6 +604,7 @@ where
|
||||||
|
|
||||||
let mut builder = Builder::new(
|
let mut builder = Builder::new(
|
||||||
hir,
|
hir,
|
||||||
|
fn_def_id.to_def_id(),
|
||||||
span_with_body,
|
span_with_body,
|
||||||
arguments.len(),
|
arguments.len(),
|
||||||
safety,
|
safety,
|
||||||
|
@ -675,8 +683,9 @@ fn construct_const<'a, 'tcx>(
|
||||||
) -> Body<'tcx> {
|
) -> Body<'tcx> {
|
||||||
let tcx = hir.tcx();
|
let tcx = hir.tcx();
|
||||||
let owner_id = tcx.hir().body_owner(body_id);
|
let owner_id = tcx.hir().body_owner(body_id);
|
||||||
|
let def_id = tcx.hir().local_def_id(owner_id);
|
||||||
let span = tcx.hir().span(owner_id);
|
let span = tcx.hir().span(owner_id);
|
||||||
let mut builder = Builder::new(hir, span, 0, Safety::Safe, const_ty, const_ty_span, None);
|
let mut builder = Builder::new(hir, def_id.to_def_id(), span, 0, Safety::Safe, const_ty, const_ty_span, None);
|
||||||
|
|
||||||
let mut block = START_BLOCK;
|
let mut block = START_BLOCK;
|
||||||
let ast_expr = &tcx.hir().body(body_id).value;
|
let ast_expr = &tcx.hir().body(body_id).value;
|
||||||
|
@ -705,6 +714,7 @@ fn construct_const<'a, 'tcx>(
|
||||||
fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> {
|
fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> {
|
||||||
let tcx = hir.tcx();
|
let tcx = hir.tcx();
|
||||||
let owner_id = tcx.hir().body_owner(body_id);
|
let owner_id = tcx.hir().body_owner(body_id);
|
||||||
|
let def_id = tcx.hir().local_def_id(owner_id);
|
||||||
let span = tcx.hir().span(owner_id);
|
let span = tcx.hir().span(owner_id);
|
||||||
let ty = tcx.ty_error();
|
let ty = tcx.ty_error();
|
||||||
let num_params = match hir.body_owner_kind {
|
let num_params = match hir.body_owner_kind {
|
||||||
|
@ -722,7 +732,7 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t
|
||||||
hir::BodyOwnerKind::Const => 0,
|
hir::BodyOwnerKind::Const => 0,
|
||||||
hir::BodyOwnerKind::Static(_) => 0,
|
hir::BodyOwnerKind::Static(_) => 0,
|
||||||
};
|
};
|
||||||
let mut builder = Builder::new(hir, span, num_params, Safety::Safe, ty, span, None);
|
let mut builder = Builder::new(hir, def_id.to_def_id(), span, num_params, Safety::Safe, ty, span, None);
|
||||||
let source_info = builder.source_info(span);
|
let source_info = builder.source_info(span);
|
||||||
// Some MIR passes will expect the number of parameters to match the
|
// Some MIR passes will expect the number of parameters to match the
|
||||||
// function declaration.
|
// function declaration.
|
||||||
|
@ -740,6 +750,7 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t
|
||||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
fn new(
|
fn new(
|
||||||
hir: Cx<'a, 'tcx>,
|
hir: Cx<'a, 'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
span: Span,
|
span: Span,
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
safety: Safety,
|
safety: Safety,
|
||||||
|
@ -750,6 +761,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let lint_level = LintLevel::Explicit(hir.root_lint_level);
|
let lint_level = LintLevel::Explicit(hir.root_lint_level);
|
||||||
let mut builder = Builder {
|
let mut builder = Builder {
|
||||||
hir,
|
hir,
|
||||||
|
def_id,
|
||||||
cfg: CFG { basic_blocks: IndexVec::new() },
|
cfg: CFG { basic_blocks: IndexVec::new() },
|
||||||
fn_span: span,
|
fn_span: span,
|
||||||
arg_count,
|
arg_count,
|
||||||
|
@ -790,6 +802,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Body::new(
|
Body::new(
|
||||||
|
MirSource::item(self.def_id),
|
||||||
self.cfg.basic_blocks,
|
self.cfg.basic_blocks,
|
||||||
self.source_scopes,
|
self.source_scopes,
|
||||||
self.local_decls,
|
self.local_decls,
|
||||||
|
|
Loading…
Reference in New Issue