You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

Abstract

Mentor and Mentee

Mentor:

Timezone:

Rocketchat (hyperledger):

Mentee: 

Timezone:

Fork of official repository for this project: 

Deliverables

Milestones

Evaluation 1:

Evaluation 2:

Evaluation 3:

Evaluation 4:

Timeline

Week #

Week

Activity

Status

0

May 24 - May 30

First contact with mentor and discussion of solutions.

1-2

May 31 - June 13


3-4

June 14 - June 27


5-6

June 28 - July 11

Evaluation 1


7-8

July 12 - July 25


9-10

July 26 - August 8


11-12

August 9 - August 22

Evaluation 2


13-14

August 23 - September 5


15-16

September 6 - September 19


17-18

September 20 - October 3

Evaluation 3


19-20

October 4 - October 17


21-22

October 18 - October 31


23-24

November 1 - November 14

Evaluation 4


Methodology

REPLACE: After I start coding each milestone, my mentor and I will have a planning session to define the best way to tackle the challenges. Then, I will execute the planning and schedule a review session with my mentor. If everything is working and we agree upon the implemented solution, I am going to write tests and update the Solang documentation website with the most recent features. In addition to those meetings, we are doing weekly calls to review the progress of the project.

Following this methodology, I intend to maintain the transparency of my work and keep the Solang users updated with the most recent features and documentation.

Documentation

REPLACE: Unused variable detection

A variable in solidity can have three scopes: a global scope, a contract scope (state variables) and a function scope. Global variables can only be constant variables. State variables reside inside a contract. After solang parses a solidity file and builds the AST (abstract syntax tree), all data is saved inside the struct Namespace, which contains a vector of contracts. Inside Contracts there is a vector of variables (struct Variable) that saves state variables. Global constant variables reside in a vector of constants inside Namespace and local variables are saved in a each function's symbol table.

We added a boolean variable read inside struct variable to signal that a variable has been used in the code. At first, used is initialized to false. Once we parse an expression that uses the variable, we set it to true. In addition, we included a boolean variable assigned to signal that a variable has been assigned. Once we parse an assignment expression, we set this variable to true. The aforementioned modification will allow us to emit warnings for unused variables and unassigned ones.

For example, in the following contract, we should expect three warnings. The variables a and b have been assigned, but never read and variable c has never been read nor assigned.


Example contract 1
contract Test {
    function get() public pure {
        uint32 a = 1;
        uint32 b;
        b = 1;
        uint32 c;

        uint32 d;
        d = 1;
        uint32 e;
        e = d*5;
        d = e/5;
   }
}


When running solidity, we got the following warnings as expected:

Warnings for Example 1
test.sol:4:16-17: warning: local variable 'a' has been assigned, but never read
test.sol:5:16-17: warning: local variable 'b' has been assigned, but never read
test.sol:7:16-17: warning: local variable 'c' has never been read nor assigned


Likewise, in the next contract, we expect to see warnings because local variable b32 has never been assigned a values, but has been read and storage variable byteArr has been assigned, but never read.

Example contract 2
contract Test {
    bytes byteArr;
    bytes32 baRR;

    function get() public  {
        string memory s = "Test";
        byteArr = bytes(s);
        uint16 a = 1;
        uint8 b;
        b = uint8(a);

        uint256 c;
        c = b;
        bytes32 b32;
        bytes memory char = bytes(bytes32(uint(a) * 2 ** (8 * b)));
        baRR = bytes32(c);
        bytes32 cdr = bytes32(char);
        assert(b32 == baRR);
        if(b32 != cdr) {

        }
    }
}


After running solidity, we got the following warnings:

Warnings for Example 2
test.sol:15:17-20: warning: local variable 'b32' has never been assigned a value, but has been read
test.sol:3:5-18: warning: storage variable 'byteArr' has been assigned, but never read

Unused variable elimination

Before creating the Control Flow Graph (CFG), Solang generates a variable table from the AST. During that phase, we can raise a warning when we see an unused variable and leave it out of the CFG. Using the id variable inside the Variable struct, we can backtrack the position where the variable appeared in the file and print a meaningful warning, containing the file name and line position. If the variable has only been assigned within a function, but has never been read, in addition to eliminating the variable declaration, we remove all the assignments from the intermediate representation.

Warning for undefined variables

During the codegen phase,  we use the reaching definitions implementation to check if an undefined definition reaches the variable we are parsing. If so, we will raise an error. Using the id variable inside the Variable struct, we backtrack the variable’s location in the source file and emit a complete warning. All warnings will be saved into the diagnostic vector, which is a vector of struct Diagnostics, containing the error type, error message and error position.

Common subexpression elimination

We perform common subexpression elimination using two passes over the Control Flow Graph (CFG). During the first on, we build a graph to track existing expressions and detect repeated ones. During the second pass, we replace the repeated expressions by a temporary variable, which assumes the value of the expression. The example below contains multiple repeated expressions:


Common subexpression elimination
contract {

    function csePass(int a, int b) {
        int x = a*b-5;
        if (x > 0) {
            x = a*b-19;
        } else {
            x = a*b*a;
        }

        return x+a*b;
    }
}


The expression `a*b` is repeated throughout the code and will be saved to a temporary variable, which will be placed wherever there is a `a*b` expression.


  • No labels