rustc_mir: enforce that arguments are replaced with Local's only.
This commit is contained in:
parent
0477319afb
commit
73f5bab33f
1 changed files with 14 additions and 41 deletions
|
@ -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)) => {
|
|
||||||
*local = l;
|
|
||||||
return;
|
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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue