1
Fork 0

refactor AbstractConstBuilder

This commit is contained in:
Bastian Kauschke 2020-09-11 09:00:21 +02:00
parent c3a772f55f
commit f24d532749

View file

@ -187,11 +187,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
} }
} }
fn build(mut self) -> Option<&'tcx [Node<'tcx>]> { fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Option<()> {
let mut block = &self.body.basic_blocks()[mir::START_BLOCK];
loop {
debug!("AbstractConstBuilder: block={:?}", block);
for stmt in block.statements.iter() {
debug!("AbstractConstBuilder: stmt={:?}", stmt); debug!("AbstractConstBuilder: stmt={:?}", stmt);
match stmt.kind { match stmt.kind {
StatementKind::Assign(box (ref place, ref rvalue)) => { StatementKind::Assign(box (ref place, ref rvalue)) => {
@ -208,9 +204,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
bug!("unexpected unchecked checkable binary operation"); bug!("unexpected unchecked checkable binary operation");
} }
} }
Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) if Self::check_binop(op) => {
if Self::check_binop(op) =>
{
let lhs = self.operand_to_node(lhs)?; let lhs = self.operand_to_node(lhs)?;
let rhs = self.operand_to_node(rhs)?; let rhs = self.operand_to_node(rhs)?;
self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs)); self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs));
@ -221,17 +215,18 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
} }
_ => return None, _ => return None,
} }
Some(())
} }
debug!("AbstractConstBuilder: terminator={:?}", block.terminator()); fn build_terminator(
match block.terminator().kind { &mut self,
TerminatorKind::Goto { target } => { terminator: &mir::Terminator<'tcx>,
block = &self.body.basic_blocks()[target]; ) -> Option<Option<mir::BasicBlock>> {
} debug!("AbstractConstBuilder: terminator={:?}", terminator);
TerminatorKind::Return => { match terminator.kind {
warn!(?self.nodes); TerminatorKind::Goto { target } => Some(Some(target)),
return { Some(self.tcx.arena.alloc_from_iter(self.nodes)) }; TerminatorKind::Return => Some(None),
}
TerminatorKind::Assert { ref cond, expected: false, target, .. } => { TerminatorKind::Assert { ref cond, expected: false, target, .. } => {
let p = match cond { let p = match cond {
mir::Operand::Copy(p) | mir::Operand::Move(p) => p, mir::Operand::Copy(p) | mir::Operand::Move(p) => p,
@ -243,14 +238,28 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() { if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() {
// Only allow asserts checking the result of a checked operation. // Only allow asserts checking the result of a checked operation.
if self.checked_op_locals.contains(p.local) { if self.checked_op_locals.contains(p.local) {
block = &self.body.basic_blocks()[target]; return Some(Some(target));
continue;
} }
} }
return None; None
} }
_ => return None, _ => None,
}
}
fn build(mut self) -> Option<&'tcx [Node<'tcx>]> {
let mut block = &self.body.basic_blocks()[mir::START_BLOCK];
loop {
debug!("AbstractConstBuilder: block={:?}", block);
for stmt in block.statements.iter() {
self.build_statement(stmt)?;
}
if let Some(next) = self.build_terminator(block.terminator())? {
block = &self.body.basic_blocks()[next];
} else {
return Some(self.tcx.arena.alloc_from_iter(self.nodes));
} }
} }
} }
@ -261,11 +270,11 @@ pub(super) fn mir_abstract_const<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>, def: ty::WithOptConstParam<LocalDefId>,
) -> Option<&'tcx [Node<'tcx>]> { ) -> Option<&'tcx [Node<'tcx>]> {
if !tcx.features().const_evaluatable_checked { if tcx.features().const_evaluatable_checked {
None
} else {
let body = tcx.mir_const(def).borrow(); let body = tcx.mir_const(def).borrow();
AbstractConstBuilder::new(tcx, &body)?.build() AbstractConstBuilder::new(tcx, &body)?.build()
} else {
None
} }
} }