Просмотр исходного кода

Dirty tracker should track all variables up to point where it is created (#898)

Signed-off-by: Lucas Steuernagel <lucas.tnagel@gmail.com>
Lucas Steuernagel 3 лет назад
Родитель
Сommit
706ab94144

+ 7 - 13
src/codegen/expression.rs

@@ -958,7 +958,6 @@ fn expr_or(
     opt: &Options,
 ) -> Expression {
     let l = expression(left, cfg, contract_no, func, ns, vartab, opt);
-    vartab.new_dirty_tracker(ns.next_id);
     let pos = vartab.temp(
         &pt::Identifier {
             name: "or".to_owned(),
@@ -966,6 +965,7 @@ fn expr_or(
         },
         &Type::Bool,
     );
+    vartab.new_dirty_tracker();
     let right_side = cfg.new_basic_block("or_right_side".to_string());
     let end_or = cfg.new_basic_block("or_end".to_string());
     cfg.add(
@@ -996,9 +996,7 @@ fn expr_or(
     );
     cfg.add(vartab, Instr::Branch { block: end_or });
     cfg.set_basic_block(end_or);
-    let mut phis = vartab.pop_dirty_tracker();
-    phis.insert(pos);
-    cfg.set_phis(end_or, phis);
+    cfg.set_phis(end_or, vartab.pop_dirty_tracker());
     Expression::Variable(*loc, Type::Bool, pos)
 }
 
@@ -1014,7 +1012,6 @@ fn and(
     opt: &Options,
 ) -> Expression {
     let l = expression(left, cfg, contract_no, func, ns, vartab, opt);
-    vartab.new_dirty_tracker(ns.next_id);
     let pos = vartab.temp(
         &pt::Identifier {
             name: "and".to_owned(),
@@ -1022,6 +1019,7 @@ fn and(
         },
         &Type::Bool,
     );
+    vartab.new_dirty_tracker();
     let right_side = cfg.new_basic_block("and_right_side".to_string());
     let end_and = cfg.new_basic_block("and_end".to_string());
     cfg.add(
@@ -1052,9 +1050,7 @@ fn and(
     );
     cfg.add(vartab, Instr::Branch { block: end_and });
     cfg.set_basic_block(end_and);
-    let mut phis = vartab.pop_dirty_tracker();
-    phis.insert(pos);
-    cfg.set_phis(end_and, phis);
+    cfg.set_phis(end_and, vartab.pop_dirty_tracker());
     Expression::Variable(*loc, Type::Bool, pos)
 }
 
@@ -1798,8 +1794,6 @@ fn ternary(
 ) -> Expression {
     let cond = expression(cond, cfg, contract_no, func, ns, vartab, opt);
 
-    vartab.new_dirty_tracker(ns.next_id);
-
     let pos = vartab.temp(
         &pt::Identifier {
             name: "ternary_result".to_owned(),
@@ -1808,6 +1802,8 @@ fn ternary(
         ty,
     );
 
+    vartab.new_dirty_tracker();
+
     let left_block = cfg.new_basic_block("left_value".to_string());
     let right_block = cfg.new_basic_block("right_value".to_string());
     let done_block = cfg.new_basic_block("ternary_done".to_string());
@@ -1853,9 +1849,7 @@ fn ternary(
 
     cfg.set_basic_block(done_block);
 
-    let mut phis = vartab.pop_dirty_tracker();
-    phis.insert(pos);
-    cfg.set_phis(done_block, phis);
+    cfg.set_phis(done_block, vartab.pop_dirty_tracker());
 
     Expression::Variable(*loc, ty.clone(), pos)
 }

+ 9 - 9
src/codegen/statements.rs

@@ -195,7 +195,7 @@ pub(crate) fn statement(
 
             cfg.set_basic_block(body);
 
-            vartab.new_dirty_tracker(ns.next_id);
+            vartab.new_dirty_tracker();
             loops.new_scope(end, cond);
 
             let mut body_reachable = true;
@@ -263,7 +263,7 @@ pub(crate) fn statement(
 
             cfg.set_basic_block(body);
 
-            vartab.new_dirty_tracker(ns.next_id);
+            vartab.new_dirty_tracker();
             loops.new_scope(end, cond);
 
             let mut body_reachable = true;
@@ -335,7 +335,7 @@ pub(crate) fn statement(
                 },
             );
 
-            vartab.new_dirty_tracker(ns.next_id);
+            vartab.new_dirty_tracker();
 
             let mut body_reachable = true;
 
@@ -443,7 +443,7 @@ pub(crate) fn statement(
             // continue goes to next
             loops.new_scope(end_block, next_block);
 
-            vartab.new_dirty_tracker(ns.next_id);
+            vartab.new_dirty_tracker();
 
             let mut body_reachable = true;
 
@@ -662,7 +662,7 @@ fn if_then(
 
     cfg.set_basic_block(then);
 
-    vartab.new_dirty_tracker(ns.next_id);
+    vartab.new_dirty_tracker();
 
     let mut reachable = true;
 
@@ -725,7 +725,7 @@ fn if_then_else(
     // then
     cfg.set_basic_block(then);
 
-    vartab.new_dirty_tracker(ns.next_id);
+    vartab.new_dirty_tracker();
 
     let mut then_reachable = true;
 
@@ -809,7 +809,7 @@ fn returns(
                 },
             );
 
-            vartab.new_dirty_tracker(ns.next_id);
+            vartab.new_dirty_tracker();
 
             cfg.set_basic_block(left_block);
             returns(left, cfg, contract_no, func, ns, vartab, opt);
@@ -882,7 +882,7 @@ fn destructure(
             },
         );
 
-        vartab.new_dirty_tracker(ns.next_id);
+        vartab.new_dirty_tracker();
 
         cfg.set_basic_block(left_block);
 
@@ -1218,7 +1218,7 @@ fn try_catch(
         _ => unreachable!(),
     }
 
-    vartab.new_dirty_tracker(ns.next_id);
+    vartab.new_dirty_tracker();
 
     let mut finally_reachable = true;
 

+ 4 - 2
src/codegen/vartable.rs

@@ -161,9 +161,11 @@ impl Vartable {
         }
     }
 
-    pub fn new_dirty_tracker(&mut self, lim: usize) {
+    /// Track dirty variables for phi instructions.
+    /// Any variable created after this command will not be considered dirty.
+    pub fn new_dirty_tracker(&mut self) {
         self.dirty.push(DirtyTracker {
-            lim,
+            lim: self.next_id,
             set: BTreeSet::new(),
         });
     }

+ 9 - 14
src/codegen/yul/builtin.rs

@@ -91,7 +91,7 @@ pub(crate) fn process_builtin(
             let mod_arg = expression(&args[2], contract_no, ns, vartab, cfg, opt);
             let (mod_left, mod_right) = equalize_types(main_expr, mod_arg, ns);
             let codegen_expr = Expression::UnsignedModulo(*loc, mod_left.ty(), Box::new(mod_left), Box::new(mod_right.clone()));
-            branch_if_zero(mod_right, codegen_expr, ns, cfg, vartab)
+            branch_if_zero(mod_right, codegen_expr, cfg, vartab)
         }
 
         YulBuiltInFunction::SignExtend
@@ -249,12 +249,12 @@ fn process_binary_arithmetic(
                 Box::new(left),
                 Box::new(right.clone()),
             );
-            branch_if_zero(right, expr, ns, cfg, vartab)
+            branch_if_zero(right, expr, cfg, vartab)
         }
         YulBuiltInFunction::SDiv => {
             let expr =
                 Expression::SignedDivide(*loc, left.ty(), Box::new(left), Box::new(right.clone()));
-            branch_if_zero(right, expr, ns, cfg, vartab)
+            branch_if_zero(right, expr, cfg, vartab)
         }
         YulBuiltInFunction::Mod => {
             let expr = Expression::UnsignedModulo(
@@ -263,12 +263,12 @@ fn process_binary_arithmetic(
                 Box::new(left),
                 Box::new(right.clone()),
             );
-            branch_if_zero(right, expr, ns, cfg, vartab)
+            branch_if_zero(right, expr, cfg, vartab)
         }
         YulBuiltInFunction::SMod => {
             let expr =
                 Expression::SignedModulo(*loc, left.ty(), Box::new(left), Box::new(right.clone()));
-            branch_if_zero(right, expr, ns, cfg, vartab)
+            branch_if_zero(right, expr, cfg, vartab)
         }
         YulBuiltInFunction::Exp => {
             Expression::Power(*loc, left.ty(), true, Box::new(left), Box::new(right))
@@ -350,7 +350,6 @@ fn equalize_types(
 fn branch_if_zero(
     variable: Expression,
     codegen_expr: Expression,
-    ns: &Namespace,
     cfg: &mut ControlFlowGraph,
     vartab: &mut Vartable,
 ) -> Expression {
@@ -378,7 +377,7 @@ fn branch_if_zero(
     );
 
     cfg.set_basic_block(then);
-    vartab.new_dirty_tracker(ns.next_id);
+    vartab.new_dirty_tracker();
     cfg.add(
         vartab,
         Instr::Set {
@@ -399,9 +398,7 @@ fn branch_if_zero(
         },
     );
     cfg.add(vartab, Instr::Branch { block: endif });
-    let mut phis = vartab.pop_dirty_tracker();
-    phis.insert(temp);
-    cfg.set_phis(endif, phis);
+    cfg.set_phis(endif, vartab.pop_dirty_tracker());
     cfg.set_basic_block(endif);
 
     Expression::Variable(pt::Loc::Codegen, Type::Uint(256), temp)
@@ -444,7 +441,7 @@ fn byte_builtin(
     );
 
     cfg.set_basic_block(then);
-    vartab.new_dirty_tracker(ns.next_id);
+    vartab.new_dirty_tracker();
     cfg.add(
         vartab,
         Instr::Set {
@@ -509,9 +506,7 @@ fn byte_builtin(
     );
     cfg.add(vartab, Instr::Branch { block: endif });
 
-    let mut phis = vartab.pop_dirty_tracker();
-    phis.insert(temp);
-    cfg.set_phis(endif, phis);
+    cfg.set_phis(endif, vartab.pop_dirty_tracker());
     cfg.set_basic_block(endif);
 
     Expression::Variable(pt::Loc::Codegen, Type::Uint(256), temp)

+ 2 - 2
src/codegen/yul/statements.rs

@@ -340,7 +340,7 @@ fn process_if_block(
     );
 
     cfg.set_basic_block(then);
-    vartab.new_dirty_tracker(ns.next_id);
+    vartab.new_dirty_tracker();
 
     for stmt in &block.body {
         statement(stmt, contract_no, loops, ns, cfg, vartab, early_return, opt);
@@ -413,7 +413,7 @@ fn process_for_block(
 
     cfg.set_basic_block(body_block);
     loops.new_scope(end_block, next_block);
-    vartab.new_dirty_tracker(ns.next_id);
+    vartab.new_dirty_tracker();
 
     for stmt in &execution_block.body {
         statement(stmt, contract_no, loops, ns, cfg, vartab, early_return, opt);