1
Fork 0

rustc_mir: enforce that arguments are replaced with Local's only.

This commit is contained in:
Eduard-Mihai Burtescu 2017-11-27 21:01:30 +02:00
parent 0477319afb
commit 73f5bab33f

View file

@ -509,7 +509,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
} }
fn cast_box_free_arg(&self, arg: Lvalue<'tcx>, ptr_ty: Ty<'tcx>, fn cast_box_free_arg(&self, arg: Lvalue<'tcx>, ptr_ty: Ty<'tcx>,
callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Operand<'tcx> { callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local {
let arg = Rvalue::Ref( let arg = Rvalue::Ref(
self.tcx.types.re_erased, self.tcx.types.re_erased,
BorrowKind::Mut, BorrowKind::Mut,
@ -539,17 +539,16 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span); let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span);
let cast_tmp = caller_mir.local_decls.push(cast_tmp); let cast_tmp = caller_mir.local_decls.push(cast_tmp);
let cast_tmp = Lvalue::Local(cast_tmp);
let cast_stmt = Statement { let cast_stmt = Statement {
source_info: callsite.location, source_info: callsite.location,
kind: StatementKind::Assign(cast_tmp.clone(), raw_ptr) kind: StatementKind::Assign(Lvalue::Local(cast_tmp), raw_ptr)
}; };
caller_mir[callsite.bb] caller_mir[callsite.bb]
.statements.push(cast_stmt); .statements.push(cast_stmt);
Operand::Consume(cast_tmp) cast_tmp
} }
fn make_call_args( fn make_call_args(
@ -557,7 +556,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
args: Vec<Operand<'tcx>>, args: Vec<Operand<'tcx>>,
callsite: &CallSite<'tcx>, callsite: &CallSite<'tcx>,
caller_mir: &mut Mir<'tcx>, caller_mir: &mut Mir<'tcx>,
) -> Vec<Operand<'tcx>> { ) -> Vec<Local> {
let tcx = self.tcx; let tcx = self.tcx;
// There is a bit of a mismatch between the *caller* of a closure and the *callee*. // There is a bit of a mismatch between the *caller* of a closure and the *callee*.
@ -589,6 +588,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir); let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir);
assert!(args.next().is_none()); assert!(args.next().is_none());
let tuple = Lvalue::Local(tuple);
let tuple_tys = if let ty::TyTuple(s, _) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty { let tuple_tys = if let ty::TyTuple(s, _) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
s s
} else { } else {
@ -596,7 +596,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
}; };
// The `closure_ref` in our example above. // The `closure_ref` in our example above.
let closure_ref_arg = iter::once(Operand::Consume(self_)); let closure_ref_arg = iter::once(self_);
// The `tmp0`, `tmp1`, and `tmp2` in our example abonve. // The `tmp0`, `tmp1`, and `tmp2` in our example abonve.
let tuple_tmp_args = let tuple_tmp_args =
@ -605,14 +605,13 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
let tuple_field = Operand::Consume(tuple.clone().field(Field::new(i), ty)); let tuple_field = Operand::Consume(tuple.clone().field(Field::new(i), ty));
// Spill to a local to make e.g. `tmp0`. // Spill to a local to make e.g. `tmp0`.
let tmp = self.create_temp_if_necessary(tuple_field, callsite, caller_mir); self.create_temp_if_necessary(tuple_field, callsite, caller_mir)
Operand::Consume(tmp)
}); });
closure_ref_arg.chain(tuple_tmp_args).collect() closure_ref_arg.chain(tuple_tmp_args).collect()
} else { } else {
args.into_iter() args.into_iter()
.map(|a| Operand::Consume(self.create_temp_if_necessary(a, callsite, caller_mir))) .map(|a| self.create_temp_if_necessary(a, callsite, caller_mir))
.collect() .collect()
} }
} }
@ -624,14 +623,14 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
arg: Operand<'tcx>, arg: Operand<'tcx>,
callsite: &CallSite<'tcx>, callsite: &CallSite<'tcx>,
caller_mir: &mut Mir<'tcx>, caller_mir: &mut Mir<'tcx>,
) -> Lvalue<'tcx> { ) -> Local {
// FIXME: Analysis of the usage of the arguments to avoid // FIXME: Analysis of the usage of the arguments to avoid
// unnecessary temporaries. // unnecessary temporaries.
if let Operand::Consume(Lvalue::Local(local)) = arg { if let Operand::Consume(Lvalue::Local(local)) = arg {
if caller_mir.local_kind(local) == LocalKind::Temp { if caller_mir.local_kind(local) == LocalKind::Temp {
// Reuse the operand if it's a temporary already // Reuse the operand if it's a temporary already
return Lvalue::Local(local); return local;
} }
} }
@ -643,11 +642,10 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span); let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span);
let arg_tmp = caller_mir.local_decls.push(arg_tmp); let arg_tmp = caller_mir.local_decls.push(arg_tmp);
let arg_tmp = Lvalue::Local(arg_tmp);
let stmt = Statement { let stmt = Statement {
source_info: callsite.location, source_info: callsite.location,
kind: StatementKind::Assign(arg_tmp.clone(), arg), kind: StatementKind::Assign(Lvalue::Local(arg_tmp), arg),
}; };
caller_mir[callsite.bb].statements.push(stmt); caller_mir[callsite.bb].statements.push(stmt);
arg_tmp arg_tmp
@ -693,7 +691,7 @@ fn subst_and_normalize<'a, 'tcx: 'a>(
*/ */
struct Integrator<'a, 'tcx: 'a> { struct Integrator<'a, 'tcx: 'a> {
block_idx: usize, block_idx: usize,
args: &'a [Operand<'tcx>], args: &'a [Local],
local_map: IndexVec<Local, Local>, local_map: IndexVec<Local, Local>,
scope_map: IndexVec<VisibilityScope, VisibilityScope>, scope_map: IndexVec<VisibilityScope, VisibilityScope>,
promoted_map: IndexVec<Promoted, Promoted>, promoted_map: IndexVec<Promoted, Promoted>,
@ -710,15 +708,6 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
debug!("Updating target `{:?}`, new: `{:?}`", tgt, new); debug!("Updating target `{:?}`, new: `{:?}`", tgt, new);
new new
} }
fn arg_index(&self, arg: Local) -> Option<usize> {
let idx = arg.index();
if idx > 0 && idx <= self.args.len() {
Some(idx - 1)
} else {
None
}
}
} }
impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
@ -737,13 +726,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
} }
let idx = local.index() - 1; let idx = local.index() - 1;
if idx < self.args.len() { if idx < self.args.len() {
match self.args[idx] { *local = self.args[idx];
Operand::Consume(Lvalue::Local(l)) => { return;
*local = l;
return;
},
ref op => bug!("Arg operand `{:?}` is {:?}, not local", idx, op)
}
} }
*local = self.local_map[Local::new(idx - self.args.len())]; *local = self.local_map[Local::new(idx - self.args.len())];
} }
@ -760,17 +744,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
} }
} }
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
if let Operand::Consume(Lvalue::Local(arg)) = *operand {
if let Some(idx) = self.arg_index(arg) {
let new_arg = self.args[idx].clone();
*operand = new_arg;
return;
}
}
self.super_operand(operand, location);
}
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
self.in_cleanup_block = data.is_cleanup; self.in_cleanup_block = data.is_cleanup;
self.super_basic_block_data(block, data); self.super_basic_block_data(block, data);