Skip to content

Commit 1a1c5c6

Browse files
committed
Add support for bitwise operations in the constant evaluator
1 parent fab296e commit 1a1c5c6

1 file changed

Lines changed: 86 additions & 5 deletions

File tree

  • crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions

crates/solidity/outputs/cargo/crate/src/backend/passes/p4_type_definitions/evaluator.rs

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,18 @@ struct CompileConstantEvaluator<'a> {
5757
impl CompileConstantEvaluator<'_> {
5858
fn evaluate_expression(&mut self, expression: &input_ir::Expression) -> Option<ConstantValue> {
5959
match expression {
60-
input_ir::Expression::BitwiseOrExpression(_bitwise_or_expression) => todo!(),
61-
input_ir::Expression::BitwiseXorExpression(_bitwise_xor_expression) => todo!(),
62-
input_ir::Expression::BitwiseAndExpression(_bitwise_and_expression) => todo!(),
63-
input_ir::Expression::ShiftExpression(_shift_expression) => todo!(),
60+
input_ir::Expression::BitwiseOrExpression(bitwise_or_expression) => {
61+
self.evaluate_bitwise_or_expression(bitwise_or_expression)
62+
}
63+
input_ir::Expression::BitwiseXorExpression(bitwise_xor_expression) => {
64+
self.evaluate_bitwise_xor_expression(bitwise_xor_expression)
65+
}
66+
input_ir::Expression::BitwiseAndExpression(bitwise_and_expression) => {
67+
self.evaluate_bitwise_and_expression(bitwise_and_expression)
68+
}
69+
input_ir::Expression::ShiftExpression(shift_expression) => {
70+
self.evaluate_shift_expression(shift_expression)
71+
}
6472
input_ir::Expression::AdditiveExpression(additive_expression) => {
6573
self.evaluate_additive_expression(additive_expression)
6674
}
@@ -86,12 +94,75 @@ impl CompileConstantEvaluator<'_> {
8694
self.evaluate_tuple_expression(tuple_expression)
8795
}
8896
_ => {
89-
// all other variants of expression cannot be evaluated at compile time
97+
// all other variants of expression cannot be evaluated at
98+
// compile time, or are not relevant for computing constant
99+
// integers (eg. string literals)
90100
None
91101
}
92102
}
93103
}
94104

105+
fn evaluate_bitwise_or_expression(
106+
&mut self,
107+
bitwise_or_expression: &input_ir::BitwiseOrExpression,
108+
) -> Option<ConstantValue> {
109+
let lhs = self.evaluate_expression(&bitwise_or_expression.left_operand)?;
110+
let rhs = self.evaluate_expression(&bitwise_or_expression.right_operand)?;
111+
match (lhs, rhs) {
112+
(ConstantValue::Integer(lhs), ConstantValue::Integer(rhs)) => {
113+
Some(ConstantValue::Integer(lhs | rhs))
114+
}
115+
}
116+
}
117+
118+
fn evaluate_bitwise_xor_expression(
119+
&mut self,
120+
bitwise_xor_expression: &input_ir::BitwiseXorExpression,
121+
) -> Option<ConstantValue> {
122+
let lhs = self.evaluate_expression(&bitwise_xor_expression.left_operand)?;
123+
let rhs = self.evaluate_expression(&bitwise_xor_expression.right_operand)?;
124+
match (lhs, rhs) {
125+
(ConstantValue::Integer(lhs), ConstantValue::Integer(rhs)) => {
126+
Some(ConstantValue::Integer(lhs ^ rhs))
127+
}
128+
}
129+
}
130+
131+
fn evaluate_bitwise_and_expression(
132+
&mut self,
133+
bitwise_and_expression: &input_ir::BitwiseAndExpression,
134+
) -> Option<ConstantValue> {
135+
let lhs = self.evaluate_expression(&bitwise_and_expression.left_operand)?;
136+
let rhs = self.evaluate_expression(&bitwise_and_expression.right_operand)?;
137+
match (lhs, rhs) {
138+
(ConstantValue::Integer(lhs), ConstantValue::Integer(rhs)) => {
139+
Some(ConstantValue::Integer(lhs & rhs))
140+
}
141+
}
142+
}
143+
144+
fn evaluate_shift_expression(
145+
&mut self,
146+
shift_expression: &input_ir::ShiftExpression,
147+
) -> Option<ConstantValue> {
148+
let lhs = self.evaluate_expression(&shift_expression.left_operand)?;
149+
let rhs = self.evaluate_expression(&shift_expression.right_operand)?;
150+
match &shift_expression.operator.kind {
151+
TerminalKind::LessThanLessThan => match (lhs, rhs) {
152+
(ConstantValue::Integer(lhs), ConstantValue::Integer(rhs)) => {
153+
Some(ConstantValue::Integer(lhs << rhs.to_u32()?))
154+
}
155+
},
156+
TerminalKind::GreaterThanGreaterThan => match (lhs, rhs) {
157+
(ConstantValue::Integer(lhs), ConstantValue::Integer(rhs)) => {
158+
Some(ConstantValue::Integer(lhs >> rhs.to_u32()?))
159+
}
160+
},
161+
TerminalKind::GreaterThanGreaterThanGreaterThan => None,
162+
_ => unreachable!("invalid operator in shift expression"),
163+
}
164+
}
165+
95166
fn evaluate_additive_expression(
96167
&mut self,
97168
additive_expression: &input_ir::AdditiveExpression,
@@ -327,6 +398,16 @@ mod tests {
327398
.is_some_and(|value| value == ConstantValue::Integer(1.to_bigint().unwrap())));
328399
assert!(eval_string("2 ** 5")
329400
.is_some_and(|value| value == ConstantValue::Integer(32.to_bigint().unwrap())));
401+
assert!(eval_string("32 << 2")
402+
.is_some_and(|value| value == ConstantValue::Integer(128.to_bigint().unwrap())));
403+
assert!(eval_string("32 >> 2")
404+
.is_some_and(|value| value == ConstantValue::Integer(8.to_bigint().unwrap())));
405+
assert!(eval_string("32 | 16")
406+
.is_some_and(|value| value == ConstantValue::Integer(48.to_bigint().unwrap())));
407+
assert!(eval_string("15 ^ 31")
408+
.is_some_and(|value| value == ConstantValue::Integer(16.to_bigint().unwrap())));
409+
assert!(eval_string("15 & 31")
410+
.is_some_and(|value| value == ConstantValue::Integer(15.to_bigint().unwrap())));
330411
}
331412

332413
#[test]

0 commit comments

Comments
 (0)