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
1 changed files with 14 additions and 41 deletions

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>,
callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Operand<'tcx> {
callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local {
let arg = Rvalue::Ref(
self.tcx.types.re_erased,
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 = caller_mir.local_decls.push(cast_tmp);
let cast_tmp = Lvalue::Local(cast_tmp);
let cast_stmt = Statement {
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]
.statements.push(cast_stmt);
Operand::Consume(cast_tmp)
cast_tmp
}
fn make_call_args(
@ -557,7 +556,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
args: Vec<Operand<'tcx>>,
callsite: &CallSite<'tcx>,
caller_mir: &mut Mir<'tcx>,
) -> Vec<Operand<'tcx>> {
) -> Vec<Local> {
let tcx = self.tcx;
// 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);
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 {
s
} else {
@ -596,7 +596,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
};
// 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.
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));
// Spill to a local to make e.g. `tmp0`.
let tmp = self.create_temp_if_necessary(tuple_field, callsite, caller_mir);
Operand::Consume(tmp)
self.create_temp_if_necessary(tuple_field, callsite, caller_mir)
});
closure_ref_arg.chain(tuple_tmp_args).collect()
} else {
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()
}
}
@ -624,14 +623,14 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
arg: Operand<'tcx>,
callsite: &CallSite<'tcx>,
caller_mir: &mut Mir<'tcx>,
) -> Lvalue<'tcx> {
) -> Local {
// FIXME: Analysis of the usage of the arguments to avoid
// unnecessary temporaries.
if let Operand::Consume(Lvalue::Local(local)) = arg {
if caller_mir.local_kind(local) == LocalKind::Temp {
// 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 = caller_mir.local_decls.push(arg_tmp);
let arg_tmp = Lvalue::Local(arg_tmp);
let stmt = Statement {
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);
arg_tmp
@ -693,7 +691,7 @@ fn subst_and_normalize<'a, 'tcx: 'a>(
*/
struct Integrator<'a, 'tcx: 'a> {
block_idx: usize,
args: &'a [Operand<'tcx>],
args: &'a [Local],
local_map: IndexVec<Local, Local>,
scope_map: IndexVec<VisibilityScope, VisibilityScope>,
promoted_map: IndexVec<Promoted, Promoted>,
@ -710,15 +708,6 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
debug!("Updating target `{:?}`, new: `{:?}`", tgt, 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> {
@ -737,13 +726,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
}
let idx = local.index() - 1;
if idx < self.args.len() {
match self.args[idx] {
Operand::Consume(Lvalue::Local(l)) => {
*local = l;
return;
},
ref op => bug!("Arg operand `{:?}` is {:?}, not local", idx, op)
}
*local = self.args[idx];
return;
}
*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>) {
self.in_cleanup_block = data.is_cleanup;
self.super_basic_block_data(block, data);