Skip to content

Commit

Permalink
[const-eval] error on invalid binary operations
Browse files Browse the repository at this point in the history
  • Loading branch information
teoxoy committed Oct 5, 2023
1 parent c0e4c11 commit 2d070b1
Showing 1 changed file with 58 additions and 14 deletions.
72 changes: 58 additions & 14 deletions src/proc/constant_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ pub enum ConstantEvaluatorError {
SubexpressionsAreNotConstant,
#[error("Not implemented as constant expression: {0}")]
NotImplemented(String),
#[error("{0} operation overflowed")]
Overflow(String),
#[error("Division by zero")]
DivisionByZero,
#[error("Remainder by zero")]
RemainderByZero,
#[error("RHS of shift operation is greater than or equal to 32")]
ShiftedMoreThan32Bits,
}

impl<'a> ConstantEvaluator<'a> {
Expand Down Expand Up @@ -990,32 +998,68 @@ impl<'a> ConstantEvaluator<'a> {

_ => match (left_value, right_value) {
(Literal::I32(a), Literal::I32(b)) => Literal::I32(match op {
BinaryOperator::Add => a.wrapping_add(b),
BinaryOperator::Subtract => a.wrapping_sub(b),
BinaryOperator::Multiply => a.wrapping_mul(b),
BinaryOperator::Divide => a.checked_div(b).unwrap_or(0),
BinaryOperator::Modulo => a.checked_rem(b).unwrap_or(0),
BinaryOperator::Add => a.checked_add(b).ok_or_else(|| {
ConstantEvaluatorError::Overflow("addition".into())
})?,
BinaryOperator::Subtract => a.checked_sub(b).ok_or_else(|| {
ConstantEvaluatorError::Overflow("subtraction".into())
})?,
BinaryOperator::Multiply => a.checked_mul(b).ok_or_else(|| {
ConstantEvaluatorError::Overflow("multiplication".into())
})?,
BinaryOperator::Divide => a.checked_div(b).ok_or_else(|| {
if b == 0 {
ConstantEvaluatorError::DivisionByZero
} else {
ConstantEvaluatorError::Overflow("division".into())
}
})?,
BinaryOperator::Modulo => a.checked_rem(b).ok_or_else(|| {
if b == 0 {
ConstantEvaluatorError::RemainderByZero
} else {
ConstantEvaluatorError::Overflow("remainder".into())
}
})?,
BinaryOperator::And => a & b,
BinaryOperator::ExclusiveOr => a ^ b,
BinaryOperator::InclusiveOr => a | b,
_ => return Err(ConstantEvaluatorError::InvalidBinaryOpArgs),
}),
(Literal::I32(a), Literal::U32(b)) => Literal::I32(match op {
BinaryOperator::ShiftLeft => a.wrapping_shl(b),
BinaryOperator::ShiftRight => a.wrapping_shr(b),
BinaryOperator::ShiftLeft => a
.checked_shl(b)
.ok_or(ConstantEvaluatorError::ShiftedMoreThan32Bits)?,
BinaryOperator::ShiftRight => a
.checked_shr(b)
.ok_or(ConstantEvaluatorError::ShiftedMoreThan32Bits)?,
_ => return Err(ConstantEvaluatorError::InvalidBinaryOpArgs),
}),
(Literal::U32(a), Literal::U32(b)) => Literal::U32(match op {
BinaryOperator::Add => a.wrapping_add(b),
BinaryOperator::Subtract => a.wrapping_sub(b),
BinaryOperator::Multiply => a.wrapping_mul(b),
BinaryOperator::Divide => a.checked_div(b).unwrap_or(0),
BinaryOperator::Modulo => a.checked_rem(b).unwrap_or(0),
BinaryOperator::Add => a.checked_add(b).ok_or_else(|| {
ConstantEvaluatorError::Overflow("addition".into())
})?,
BinaryOperator::Subtract => a.checked_sub(b).ok_or_else(|| {
ConstantEvaluatorError::Overflow("subtraction".into())
})?,
BinaryOperator::Multiply => a.checked_mul(b).ok_or_else(|| {
ConstantEvaluatorError::Overflow("multiplication".into())
})?,
BinaryOperator::Divide => a
.checked_div(b)
.ok_or(ConstantEvaluatorError::DivisionByZero)?,
BinaryOperator::Modulo => a
.checked_rem(b)
.ok_or(ConstantEvaluatorError::RemainderByZero)?,
BinaryOperator::And => a & b,
BinaryOperator::ExclusiveOr => a ^ b,
BinaryOperator::InclusiveOr => a | b,
BinaryOperator::ShiftLeft => a.wrapping_shl(b),
BinaryOperator::ShiftRight => a.wrapping_shr(b),
BinaryOperator::ShiftLeft => a
.checked_shl(b)
.ok_or(ConstantEvaluatorError::ShiftedMoreThan32Bits)?,
BinaryOperator::ShiftRight => a
.checked_shr(b)
.ok_or(ConstantEvaluatorError::ShiftedMoreThan32Bits)?,
_ => return Err(ConstantEvaluatorError::InvalidBinaryOpArgs),
}),
(Literal::F32(a), Literal::F32(b)) => Literal::F32(match op {
Expand Down

0 comments on commit 2d070b1

Please sign in to comment.