diff options
Diffstat (limited to 'src/librustc_mir/transform/add_validation.rs')
| -rw-r--r-- | src/librustc_mir/transform/add_validation.rs | 83 |
1 files changed, 43 insertions, 40 deletions
diff --git a/src/librustc_mir/transform/add_validation.rs b/src/librustc_mir/transform/add_validation.rs index 8fad538af97..f0f6add3f6f 100644 --- a/src/librustc_mir/transform/add_validation.rs +++ b/src/librustc_mir/transform/add_validation.rs @@ -17,22 +17,22 @@ use rustc::ty::{self, TyCtxt, RegionKind}; use rustc::hir; use rustc::mir::*; -use rustc::mir::transform::{MirPass, MirSource}; use rustc::middle::region; +use transform::{MirPass, MirSource}; pub struct AddValidation; -/// Determine the "context" of the lval: Mutability and region. -fn lval_context<'a, 'tcx, D>( - lval: &Lvalue<'tcx>, +/// Determine the "context" of the place: Mutability and region. +fn place_context<'a, 'tcx, D>( + place: &Place<'tcx>, local_decls: &D, tcx: TyCtxt<'a, 'tcx, 'tcx> ) -> (Option<region::Scope>, hir::Mutability) where D: HasLocalDecls<'tcx> { - use rustc::mir::Lvalue::*; + use rustc::mir::Place::*; - match *lval { + match *place { Local { .. } => (None, hir::MutMutable), Static(_) => (None, hir::MutImmutable), Projection(ref proj) => { @@ -66,7 +66,7 @@ fn lval_context<'a, 'tcx, D>( // This is already as restricted as it gets, no need to even recurse context } else { - let base_context = lval_context(&proj.base, local_decls, tcx); + let base_context = place_context(&proj.base, local_decls, tcx); // The region of the outermost Deref is always most restrictive. let re = context.0.or(base_context.0); let mutbl = context.1.and(base_context.1); @@ -74,7 +74,7 @@ fn lval_context<'a, 'tcx, D>( } } - _ => lval_context(&proj.base, local_decls, tcx), + _ => place_context(&proj.base, local_decls, tcx), } } } @@ -106,8 +106,9 @@ fn fn_contains_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource) -> } } - let fn_like = match src { - MirSource::Fn(node_id) => { + let node_id = tcx.hir.as_local_node_id(src.def_id).unwrap(); + let fn_like = match tcx.hir.body_owner_kind(node_id) { + hir::BodyOwnerKind::Fn => { match FnLikeNode::from_node(tcx.hir.get(node_id)) { Some(fn_like) => fn_like, None => return false, // e.g. struct ctor shims -- such auto-generated code cannot @@ -197,11 +198,11 @@ impl MirPass for AddValidation { let restricted_validation = emit_validate == 1 && fn_contains_unsafe(tcx, src); let local_decls = mir.local_decls.clone(); // FIXME: Find a way to get rid of this clone. - // Convert an lvalue to a validation operand. - let lval_to_operand = |lval: Lvalue<'tcx>| -> ValidationOperand<'tcx, Lvalue<'tcx>> { - let (re, mutbl) = lval_context(&lval, &local_decls, tcx); - let ty = lval.ty(&local_decls, tcx).to_ty(tcx); - ValidationOperand { lval, ty, re, mutbl } + // Convert a place to a validation operand. + let place_to_operand = |place: Place<'tcx>| -> ValidationOperand<'tcx, Place<'tcx>> { + let (re, mutbl) = place_context(&place, &local_decls, tcx); + let ty = place.ty(&local_decls, tcx).to_ty(tcx); + ValidationOperand { place, ty, re, mutbl } }; // Emit an Acquire at the beginning of the given block. If we are in restricted emission @@ -236,14 +237,14 @@ impl MirPass for AddValidation { }; // Gather all arguments, skip return value. let operands = mir.local_decls.iter_enumerated().skip(1).take(mir.arg_count) - .map(|(local, _)| lval_to_operand(Lvalue::Local(local))).collect(); + .map(|(local, _)| place_to_operand(Place::Local(local))).collect(); emit_acquire(&mut mir.basic_blocks_mut()[START_BLOCK], source_info, operands); } // PART 2 // Add ReleaseValid/AcquireValid around function call terminators. We don't use a visitor // because we need to access the block that a Call jumps to. - let mut returns : Vec<(SourceInfo, Lvalue<'tcx>, BasicBlock)> = Vec::new(); + let mut returns : Vec<(SourceInfo, Place<'tcx>, BasicBlock)> = Vec::new(); for block_data in mir.basic_blocks_mut() { match block_data.terminator { Some(Terminator { kind: TerminatorKind::Call { ref args, ref destination, .. }, @@ -255,12 +256,13 @@ impl MirPass for AddValidation { let release_stmt = Statement { source_info, kind: StatementKind::Validate(ValidationOp::Release, - destination.iter().map(|dest| lval_to_operand(dest.0.clone())) + destination.iter().map(|dest| place_to_operand(dest.0.clone())) .chain( args.iter().filter_map(|op| { match op { - &Operand::Consume(ref lval) => - Some(lval_to_operand(lval.clone())), + &Operand::Copy(ref place) | + &Operand::Move(ref place) => + Some(place_to_operand(place.clone())), &Operand::Constant(..) => { None }, } }) @@ -273,16 +275,16 @@ impl MirPass for AddValidation { returns.push((source_info, destination.0.clone(), destination.1)); } } - Some(Terminator { kind: TerminatorKind::Drop { location: ref lval, .. }, + Some(Terminator { kind: TerminatorKind::Drop { location: ref place, .. }, source_info }) | - Some(Terminator { kind: TerminatorKind::DropAndReplace { location: ref lval, .. }, + Some(Terminator { kind: TerminatorKind::DropAndReplace { location: ref place, .. }, source_info }) => { // Before the call: Release all arguments if !restricted_validation { let release_stmt = Statement { source_info, kind: StatementKind::Validate(ValidationOp::Release, - vec![lval_to_operand(lval.clone())]), + vec![place_to_operand(place.clone())]), }; block_data.statements.push(release_stmt); } @@ -294,11 +296,11 @@ impl MirPass for AddValidation { } } // Now we go over the returns we collected to acquire the return values. - for (source_info, dest_lval, dest_block) in returns { + for (source_info, dest_place, dest_block) in returns { emit_acquire( &mut mir.basic_blocks_mut()[dest_block], source_info, - vec![lval_to_operand(dest_lval)] + vec![place_to_operand(dest_place)] ); } @@ -319,22 +321,20 @@ impl MirPass for AddValidation { StatementKind::Assign(_, Rvalue::Ref(_, _, _)) => { // Due to a lack of NLL; we can't capture anything directly here. // Instead, we have to re-match and clone there. - let (dest_lval, re, src_lval) = match block_data.statements[i].kind { - StatementKind::Assign(ref dest_lval, - Rvalue::Ref(re, _, ref src_lval)) => { - (dest_lval.clone(), re, src_lval.clone()) + let (dest_place, re, src_place) = match block_data.statements[i].kind { + StatementKind::Assign(ref dest_place, + Rvalue::Ref(re, _, ref src_place)) => { + (dest_place.clone(), re, src_place.clone()) }, _ => bug!("We already matched this."), }; // So this is a ref, and we got all the data we wanted. // Do an acquire of the result -- but only what it points to, so add a Deref // projection. - let dest_lval = Projection { base: dest_lval, elem: ProjectionElem::Deref }; - let dest_lval = Lvalue::Projection(Box::new(dest_lval)); let acquire_stmt = Statement { source_info: block_data.statements[i].source_info, kind: StatementKind::Validate(ValidationOp::Acquire, - vec![lval_to_operand(dest_lval)]), + vec![place_to_operand(dest_place.deref())]), }; block_data.statements.insert(i+1, acquire_stmt); @@ -347,21 +347,24 @@ impl MirPass for AddValidation { }; let release_stmt = Statement { source_info: block_data.statements[i].source_info, - kind: StatementKind::Validate(op, vec![lval_to_operand(src_lval)]), + kind: StatementKind::Validate(op, vec![place_to_operand(src_place)]), }; block_data.statements.insert(i, release_stmt); } // Casts can change what validation does (e.g. unsizing) - StatementKind::Assign(_, Rvalue::Cast(kind, Operand::Consume(_), _)) + StatementKind::Assign(_, Rvalue::Cast(kind, Operand::Copy(_), _)) | + StatementKind::Assign(_, Rvalue::Cast(kind, Operand::Move(_), _)) if kind != CastKind::Misc => { // Due to a lack of NLL; we can't capture anything directly here. // Instead, we have to re-match and clone there. - let (dest_lval, src_lval) = match block_data.statements[i].kind { - StatementKind::Assign(ref dest_lval, - Rvalue::Cast(_, Operand::Consume(ref src_lval), _)) => + let (dest_place, src_place) = match block_data.statements[i].kind { + StatementKind::Assign(ref dest_place, + Rvalue::Cast(_, Operand::Copy(ref src_place), _)) | + StatementKind::Assign(ref dest_place, + Rvalue::Cast(_, Operand::Move(ref src_place), _)) => { - (dest_lval.clone(), src_lval.clone()) + (dest_place.clone(), src_place.clone()) }, _ => bug!("We already matched this."), }; @@ -370,7 +373,7 @@ impl MirPass for AddValidation { let acquire_stmt = Statement { source_info: block_data.statements[i].source_info, kind: StatementKind::Validate(ValidationOp::Acquire, - vec![lval_to_operand(dest_lval)]), + vec![place_to_operand(dest_place)]), }; block_data.statements.insert(i+1, acquire_stmt); @@ -378,7 +381,7 @@ impl MirPass for AddValidation { let release_stmt = Statement { source_info: block_data.statements[i].source_info, kind: StatementKind::Validate(ValidationOp::Release, - vec![lval_to_operand(src_lval)]), + vec![place_to_operand(src_place)]), }; block_data.statements.insert(i, release_stmt); } |
