mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 22:41:50 +00:00
Implement a pass manager
This commit is contained in:
parent
a0de6346de
commit
c1a501b131
@ -16,6 +16,7 @@ use rustc_hir::def::{CtorKind, Namespace};
|
||||
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
use rustc_hir::{self, GeneratorKind};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_session::Session;
|
||||
use rustc_target::abi::{Size, VariantIdx};
|
||||
|
||||
use polonius_engine::Atom;
|
||||
@ -99,7 +100,21 @@ pub trait MirPass<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this pass is enabled with the current combination of compiler flags.
|
||||
fn is_enabled(&self, _sess: &Session) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>);
|
||||
|
||||
/// If this pass causes the MIR to enter a new phase, return that phase.
|
||||
fn phase_change(&self) -> Option<MirPhase> {
|
||||
None
|
||||
}
|
||||
|
||||
fn is_mir_dump_enabled(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// The various "big phases" that MIR goes through.
|
||||
|
@ -32,6 +32,11 @@ use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
#[macro_use]
|
||||
mod pass_manager;
|
||||
|
||||
use pass_manager::{Lint, MirLint};
|
||||
|
||||
mod abort_unwinding_calls;
|
||||
mod add_call_guards;
|
||||
mod add_moves_for_packed_drops;
|
||||
|
121
compiler/rustc_mir_transform/src/pass_manager.rs
Normal file
121
compiler/rustc_mir_transform/src/pass_manager.rs
Normal file
@ -0,0 +1,121 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use rustc_middle::mir::{self, Body, MirPhase};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
|
||||
use crate::{validate, MirPass};
|
||||
|
||||
/// Just like `MirPass`, except it cannot mutate `Body`.
|
||||
pub trait MirLint<'tcx> {
|
||||
fn name(&self) -> Cow<'_, str> {
|
||||
let name = std::any::type_name::<Self>();
|
||||
if let Some(tail) = name.rfind(':') {
|
||||
Cow::from(&name[tail + 1..])
|
||||
} else {
|
||||
Cow::from(name)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_enabled(&self, _sess: &Session) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>);
|
||||
}
|
||||
|
||||
/// An adapter for `MirLint`s that implements `MirPass`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Lint<T>(pub T);
|
||||
|
||||
impl<T> MirPass<'tcx> for Lint<T>
|
||||
where
|
||||
T: MirLint<'tcx>,
|
||||
{
|
||||
fn name(&self) -> Cow<'_, str> {
|
||||
self.0.name()
|
||||
}
|
||||
|
||||
fn is_enabled(&self, sess: &Session) -> bool {
|
||||
self.0.is_enabled(sess)
|
||||
}
|
||||
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
self.0.run_lint(tcx, body)
|
||||
}
|
||||
|
||||
fn is_mir_dump_enabled(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_passes(tcx: TyCtxt<'tcx>, body: &'mir mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) {
|
||||
let start_phase = body.phase;
|
||||
let mut cnt = 0;
|
||||
|
||||
let validate = tcx.sess.opts.debugging_opts.validate_mir;
|
||||
|
||||
if validate {
|
||||
validate_body(tcx, body, format!("start of phase transition from {:?}", start_phase));
|
||||
}
|
||||
|
||||
for pass in passes {
|
||||
if !pass.is_enabled(&tcx.sess) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = pass.name();
|
||||
let dump_enabled = pass.is_mir_dump_enabled();
|
||||
|
||||
if dump_enabled {
|
||||
dump_mir(tcx, body, start_phase, &name, cnt, false);
|
||||
}
|
||||
|
||||
pass.run_pass(tcx, body);
|
||||
|
||||
if dump_enabled {
|
||||
dump_mir(tcx, body, start_phase, &name, cnt, true);
|
||||
cnt += 1;
|
||||
}
|
||||
|
||||
if let Some(new_phase) = pass.phase_change() {
|
||||
if body.phase >= new_phase {
|
||||
panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase);
|
||||
}
|
||||
|
||||
body.phase = new_phase;
|
||||
}
|
||||
|
||||
if validate {
|
||||
validate_body(tcx, body, format!("after pass {}", pass.name()));
|
||||
}
|
||||
}
|
||||
|
||||
if validate || body.phase == MirPhase::Optimization {
|
||||
validate_body(tcx, body, format!("end of phase transition to {:?}", body.phase));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_body(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) {
|
||||
validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body);
|
||||
}
|
||||
|
||||
pub fn dump_mir(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
phase: MirPhase,
|
||||
pass_name: &str,
|
||||
cnt: usize,
|
||||
is_after: bool,
|
||||
) {
|
||||
let phase_index = phase as u32;
|
||||
|
||||
mir::dump_mir(
|
||||
tcx,
|
||||
Some(&format_args!("{:03}-{:03}", phase_index, cnt)),
|
||||
pass_name,
|
||||
if is_after { &"after" } else { &"before" },
|
||||
body,
|
||||
|_, _| Ok(()),
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user