diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c592882a1e4..68e6b0f50d1 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -925,6 +925,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut passes = Passes::new(); passes.push_hook(mir::transform::dump_mir::DumpMir); + // Insert AcquireValid and ReleaseValid calls. Conceptually, this + // pass is actually part of MIR building. + passes.push_pass(MIR_CONST, mir::transform::add_validation::AddValidation); + // Remove all `EndRegion` statements that are not involved in borrows. passes.push_pass(MIR_CONST, mir::transform::clean_end_regions::CleanEndRegions); diff --git a/src/librustc_mir/transform/add_validation.rs b/src/librustc_mir/transform/add_validation.rs new file mode 100644 index 00000000000..6934ec7a74f --- /dev/null +++ b/src/librustc_mir/transform/add_validation.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This pass adds validation calls (AcquireValid, ReleaseValid) where appropriate. +//! It has to be run really early, before transformations like inlining, because +//! introducing these calls *adds* UB -- so, conceptually, this pass is actually part +//! of MIR building, and only after this pass we think of the program has having the +//! normal MIR semantics. + +use rustc::ty::TyCtxt; +use rustc::mir::*; +use rustc::mir::transform::{MirPass, MirSource}; + +pub struct AddValidation; + +impl MirPass for AddValidation { + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _: MirSource, + mir: &mut Mir<'tcx>) { + // Add an AcquireValid at the beginning of the start block + if mir.arg_count > 0 { + let acquire_stmt = Statement { + source_info: SourceInfo { + scope: ARGUMENT_VISIBILITY_SCOPE, + span: mir.span, + }, + kind: StatementKind::Validate(ValidationOp::Acquire, + // Skip return value, go over all the arguments + mir.local_decls.iter_enumerated().skip(1).take(mir.arg_count) + .map(|(local, local_decl)| (local_decl.ty, Lvalue::Local(local))).collect()) + }; + mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, acquire_stmt); + } + } +} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index c9c8ad0e0eb..a247ce2231e 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -24,6 +24,7 @@ use syntax::ast; use syntax_pos::{DUMMY_SP, Span}; use transform; +pub mod add_validation; pub mod clean_end_regions; pub mod simplify_branches; pub mod simplify;