Browse Source

Replace Expression::DynamicArrayLength with builtin

This is a type of builtin, not an type of an expression.

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 3 years ago
parent
commit
588f3912fd

+ 0 - 3
src/bin/languageserver/mod.rs

@@ -601,9 +601,6 @@ impl SolangServer {
             ast::Expression::AllocDynamicArray(_locs, _typ, expr1, _valvec) => {
                 SolangServer::construct_expr(expr1, lookup_tbl, symtab, fnc_map, ns);
             }
-            ast::Expression::DynamicArrayLength(_locs, expr1) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, fnc_map, ns);
-            }
             ast::Expression::StorageBytesSubscript(_locs, expr1, expr2) => {
                 SolangServer::construct_expr(expr1, lookup_tbl, symtab, fnc_map, ns);
                 SolangServer::construct_expr(expr2, lookup_tbl, symtab, fnc_map, ns);

+ 0 - 3
src/codegen/cfg.rs

@@ -614,9 +614,6 @@ impl ControlFlowGraph {
                     Err(_) => format!("hex\"{}\"", hex::encode(init)),
                 }
             ),
-            Expression::DynamicArrayLength(_, a) => {
-                format!("(darray {} len)", self.expr_to_string(contract, ns, a))
-            }
             Expression::StringCompare(_, l, r) => format!(
                 "(strcmp ({}) ({}))",
                 self.location_to_string(contract, ns, l),

+ 0 - 8
src/codegen/constant_folding.rs

@@ -936,14 +936,6 @@ fn expression(
                 false,
             )
         }
-        Expression::DynamicArrayLength(loc, array) => {
-            let array = expression(array, vars, pos, cfg, ns);
-
-            (
-                Expression::DynamicArrayLength(*loc, Box::new(array.0)),
-                false,
-            )
-        }
         Expression::StorageBytesSubscript(loc, array, index) => {
             let array = expression(array, vars, pos, cfg, ns);
             let index = expression(index, vars, pos, cfg, ns);

+ 12 - 6
src/codegen/expression.rs

@@ -474,10 +474,6 @@ pub fn expression(
             string_location(left, cfg, contract_no, func, ns, vartab, opt),
             string_location(right, cfg, contract_no, func, ns, vartab, opt),
         ),
-        Expression::DynamicArrayLength(loc, expr) => Expression::DynamicArrayLength(
-            *loc,
-            Box::new(expression(expr, cfg, contract_no, func, ns, vartab, opt)),
-        ),
         Expression::Or(loc, left, right) => {
             expr_or(left, cfg, contract_no, func, ns, vartab, loc, right, opt)
         }
@@ -2087,14 +2083,24 @@ fn array_subscript(
                         array_length
                     }
                 } else {
-                    Expression::DynamicArrayLength(*loc, Box::new(array.clone()))
+                    Expression::Builtin(
+                        *loc,
+                        vec![Type::Uint(32)],
+                        Builtin::ArrayLength,
+                        vec![array.clone()],
+                    )
                 }
             }
             Some(l) => {
                 bigint_to_expression(loc, l, ns, &mut Vec::new(), ResolveTo::Unknown).unwrap()
             }
         },
-        Type::DynamicBytes => Expression::DynamicArrayLength(*loc, Box::new(array.clone())),
+        Type::DynamicBytes => Expression::Builtin(
+            *loc,
+            vec![Type::Uint(32)],
+            Builtin::ArrayLength,
+            vec![array.clone()],
+        ),
         _ => {
             unreachable!();
         }

+ 2 - 2
src/codegen/undefined_variable.rs

@@ -1,7 +1,7 @@
 use crate::codegen::cfg::{ControlFlowGraph, Instr};
 use crate::codegen::reaching_definitions::{apply_transfers, VarDefs};
 use crate::parser::pt::{Loc, StorageLocation};
-use crate::sema::ast::{Diagnostic, ErrorType, Expression, Level, Namespace, Note};
+use crate::sema::ast::{Builtin, Diagnostic, ErrorType, Expression, Level, Namespace, Note};
 use crate::sema::symtable;
 use std::collections::HashMap;
 
@@ -96,7 +96,7 @@ pub fn find_undefined_variables_in_expression(
         }
 
         // This is a method call whose array will never be undefined
-        Expression::DynamicArrayLength(..) => false,
+        Expression::Builtin(_, _, Builtin::ArrayLength, _) => false,
 
         _ => true,
     }

+ 2 - 2
src/emit/mod.rs

@@ -2549,8 +2549,8 @@ pub trait TargetRuntime<'a> {
                     bin.vector_new(size, elem_size, init.as_ref()).into()
                 }
             }
-            Expression::DynamicArrayLength(_, a) => {
-                let array = self.expression(bin, a, vartab, function, ns);
+            Expression::Builtin(_, _, Builtin::ArrayLength, args) => {
+                let array = self.expression(bin, &args[0], vartab, function, ns);
 
                 bin.vector_len(array).into()
             }

+ 2 - 7
src/sema/ast.rs

@@ -547,7 +547,6 @@ pub enum Expression {
     StructMember(pt::Loc, Type, Box<Expression>, usize),
 
     AllocDynamicArray(pt::Loc, Type, Box<Expression>, Option<Vec<u8>>),
-    DynamicArrayLength(pt::Loc, Box<Expression>),
     StorageBytesSubscript(pt::Loc, Box<Expression>, Box<Expression>),
     StorageArrayLength {
         loc: pt::Loc,
@@ -832,9 +831,6 @@ impl Expression {
                         initializer.clone(),
                     )
                 }
-                Expression::DynamicArrayLength(loc, expr) => {
-                    Expression::DynamicArrayLength(*loc, Box::new(filter(expr, ctx)))
-                }
                 Expression::StorageBytesSubscript(loc, storage, index) => {
                     Expression::StorageBytesSubscript(
                         *loc,
@@ -1064,8 +1060,7 @@ impl Expression {
                 }
                 Expression::StructMember(_, _, expr, _) => expr.recurse(cx, f),
 
-                Expression::AllocDynamicArray(_, _, expr, _)
-                | Expression::DynamicArrayLength(_, expr) => expr.recurse(cx, f),
+                Expression::AllocDynamicArray(_, _, expr, _) => expr.recurse(cx, f),
                 Expression::StorageBytesSubscript(_, left, right) => {
                     left.recurse(cx, f);
                     right.recurse(cx, f);
@@ -1215,7 +1210,6 @@ impl Expression {
             | Expression::StructMember(loc, _, _, _)
             | Expression::Or(loc, _, _)
             | Expression::AllocDynamicArray(loc, _, _, _)
-            | Expression::DynamicArrayLength(loc, _)
             | Expression::StorageBytesSubscript(loc, _, _)
             | Expression::StorageArrayLength { loc, .. }
             | Expression::StringCompare(loc, _, _)
@@ -1279,6 +1273,7 @@ pub enum Builtin {
     PayableTransfer,
     ArrayPush,
     ArrayPop,
+    ArrayLength,
     Assert,
     Print,
     Revert,

+ 0 - 15
src/sema/dotgraphviz.rs

@@ -922,21 +922,6 @@ impl Dot {
 
                 self.add_expression(length, func, ns, node, String::from("length"));
             }
-            Expression::DynamicArrayLength(loc, expr) => {
-                let node = self.add_node(
-                    Node::new(
-                        "array_length",
-                        vec![
-                            String::from("array length"),
-                            ns.files[loc.0].loc_to_string(loc),
-                        ],
-                    ),
-                    Some(parent),
-                    Some(parent_rel),
-                );
-
-                self.add_expression(expr, func, ns, node, String::from("expr"));
-            }
 
             Expression::StorageBytesSubscript(loc, array, index) => {
                 let node = self.add_node(

+ 12 - 3
src/sema/expression.rs

@@ -92,7 +92,6 @@ impl Expression {
                 ty.storage_array_elem()
             }
             Expression::Subscript(_, ty, _, _) => ty.array_deref(),
-            Expression::DynamicArrayLength(_, _) => Type::Uint(32),
             Expression::StorageArrayLength { ty, .. } => ty.clone(),
             Expression::StorageBytesSubscript(_, _, _) => {
                 Type::StorageRef(false, Box::new(Type::Bytes(1)))
@@ -4214,7 +4213,12 @@ fn member_access(
         Type::Array(_, dim) => {
             if id.name == "length" {
                 return match dim.last().unwrap() {
-                    None => Ok(Expression::DynamicArrayLength(*loc, Box::new(expr))),
+                    None => Ok(Expression::Builtin(
+                        *loc,
+                        vec![Type::Uint(32)],
+                        Builtin::ArrayLength,
+                        vec![expr],
+                    )),
                     Some(d) => {
                         //We should not eliminate an array from the code when 'length' is called
                         //So the variable is also assigned a value to be read from 'length'
@@ -4233,7 +4237,12 @@ fn member_access(
         }
         Type::String | Type::DynamicBytes => {
             if id.name == "length" {
-                return Ok(Expression::DynamicArrayLength(*loc, Box::new(expr)));
+                return Ok(Expression::Builtin(
+                    *loc,
+                    vec![Type::Uint(32)],
+                    Builtin::ArrayLength,
+                    vec![expr],
+                ));
             }
         }
         Type::StorageRef(immutable, r) => match *r {

+ 0 - 4
src/sema/printer.rs

@@ -456,10 +456,6 @@ fn print_expr(e: &Expression, func: Option<&Function>, ns: &Namespace) -> Tree {
                 Tree::Leaf(format!("init {}", hex::encode(init))),
             ],
         ),
-        Expression::DynamicArrayLength(_, array) => Tree::Branch(
-            String::from("dynamic array length"),
-            vec![print_expr(array, func, ns)],
-        ),
         Expression::StorageBytesSubscript(_, array, index) => Tree::Branch(
             String::from("storage bytes subscript"),
             vec![

+ 7 - 2
src/sema/unused_variable.rs

@@ -71,8 +71,13 @@ pub fn used_variable(ns: &mut Namespace, exp: &Expression, symtable: &mut Symtab
             used_variable(ns, index, symtable);
         }
 
-        Expression::DynamicArrayLength(_, array)
-        | Expression::StorageArrayLength {
+        Expression::Builtin(_, _, Builtin::ArrayLength, args) => {
+            //We should not eliminate an array from the code when 'length' is called
+            //So the variable is also assigned
+            assigned_variable(ns, &args[0], symtable);
+            used_variable(ns, &args[0], symtable);
+        }
+        Expression::StorageArrayLength {
             loc: _,
             ty: _,
             array,

+ 1 - 1
tests/codegen_testcases/common_subexpression_elimination.sol

@@ -372,7 +372,7 @@ contract c1 {
             string k = testing(bytes(c));
             string p = "a" +k;
             // CHECK: ty:string %p = (concat ((alloc string uint32 1 "a")) (%k))
-            // CHECK: branchcond ((darray %p len) == uint32 2), block11, block12
+            // CHECK: branchcond ((builtin ArrayLength (%p)) == uint32 2), block11, block12
             if(p.length == 2) {
                 // CHECK: ty:string %p1 = (concat ((alloc string uint32 1 "a")) (%k))
                 string p1 = "a" + k;