diff options
author | chriseth <chris@ethereum.org> | 2018-12-13 22:26:01 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2018-12-13 23:49:04 +0800 |
commit | 11209ec48a3581419ebfa4764669c2a128f1b997 (patch) | |
tree | 29e6a72de33ebd31dc9f0fc1fab7efa7fdc87dfb | |
parent | 633dd44576e267f4728b86ec69a9cc56517a1f89 (diff) | |
download | dexon-solidity-11209ec48a3581419ebfa4764669c2a128f1b997.tar.gz dexon-solidity-11209ec48a3581419ebfa4764669c2a128f1b997.tar.zst dexon-solidity-11209ec48a3581419ebfa4764669c2a128f1b997.zip |
Add variable declaration initializer.
-rw-r--r-- | libyul/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libyul/optimiser/Suite.cpp | 2 | ||||
-rw-r--r-- | libyul/optimiser/VarDeclInitializer.cpp | 56 | ||||
-rw-r--r-- | libyul/optimiser/VarDeclInitializer.h | 38 | ||||
-rw-r--r-- | test/libyul/YulOptimizerTest.cpp | 3 | ||||
-rw-r--r-- | test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul | 29 | ||||
-rw-r--r-- | test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul | 24 | ||||
-rw-r--r-- | test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul | 14 | ||||
-rw-r--r-- | test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul | 21 | ||||
-rw-r--r-- | test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul | 8 |
10 files changed, 196 insertions, 0 deletions
diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 74a5703c..9dee5348 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -44,5 +44,6 @@ add_library(yul optimiser/UnusedPruner.cpp optimiser/Utilities.cpp optimiser/VarDeclPropagator.cpp + optimiser/VarDeclInitializer.cpp ) target_link_libraries(yul PUBLIC evmasm devcore langutil) diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index ad22bfa3..16df6d3c 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -21,6 +21,7 @@ #include <libyul/optimiser/Suite.h> #include <libyul/optimiser/Disambiguator.h> +#include <libyul/optimiser/VarDeclInitializer.h> #include <libyul/optimiser/FunctionGrouper.h> #include <libyul/optimiser/FunctionHoister.h> #include <libyul/optimiser/ExpressionSplitter.h> @@ -56,6 +57,7 @@ void OptimiserSuite::run( Block ast = boost::get<Block>(Disambiguator(_analysisInfo, reservedIdentifiers)(_ast)); + (VarDeclInitializer{})(ast); (FunctionHoister{})(ast); (FunctionGrouper{})(ast); (ForLoopInitRewriter{})(ast); diff --git a/libyul/optimiser/VarDeclInitializer.cpp b/libyul/optimiser/VarDeclInitializer.cpp new file mode 100644 index 00000000..4a26757f --- /dev/null +++ b/libyul/optimiser/VarDeclInitializer.cpp @@ -0,0 +1,56 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <libyul/optimiser/VarDeclInitializer.h> +#include <libyul/AsmData.h> + +#include <libdevcore/CommonData.h> +#include <libdevcore/Visitor.h> + +using namespace std; +using namespace dev; +using namespace yul; + +void VarDeclInitializer::operator()(Block& _block) +{ + ASTModifier::operator()(_block); + + static Expression const zero{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}}; + + using OptionalStatements = boost::optional<vector<Statement>>; + GenericFallbackReturnsVisitor<OptionalStatements, VariableDeclaration> visitor{ + [](VariableDeclaration& _varDecl) -> OptionalStatements + { + if (_varDecl.value) + return {}; + else if (_varDecl.variables.size() == 1) + { + _varDecl.value = make_shared<Expression>(zero); + return {}; + } + else + { + OptionalStatements ret{vector<Statement>{}}; + langutil::SourceLocation loc{std::move(_varDecl.location)}; + for (auto& var: _varDecl.variables) + ret->push_back(VariableDeclaration{loc, {std::move(var)}, make_shared<Expression>(zero)}); + return ret; + } + } + }; + iterateReplacing(_block.statements, boost::apply_visitor(visitor)); +} diff --git a/libyul/optimiser/VarDeclInitializer.h b/libyul/optimiser/VarDeclInitializer.h new file mode 100644 index 00000000..41d0917c --- /dev/null +++ b/libyul/optimiser/VarDeclInitializer.h @@ -0,0 +1,38 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include <libyul/AsmDataForward.h> +#include <libyul/optimiser/ASTWalker.h> + +namespace yul +{ + +/** + * Rewrites variable declarations so that all of them are initialized. + * Declarations like ``let x, y`` are split into multiple declaration + * statements. + * Only supports initializing with the zero literal for now. + */ +class VarDeclInitializer: public ASTModifier +{ +public: + void operator()(Block& _block) override; +}; + +} diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 68226e33..68de563d 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -23,6 +23,7 @@ #include <libyul/optimiser/BlockFlattener.h> #include <libyul/optimiser/VarDeclPropagator.h> +#include <libyul/optimiser/VarDeclInitializer.h> #include <libyul/optimiser/Disambiguator.h> #include <libyul/optimiser/CommonSubexpressionEliminator.h> #include <libyul/optimiser/NameCollector.h> @@ -112,6 +113,8 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); VarDeclPropagator{}(*m_ast); } + else if (m_optimizerStep == "varDeclInitializer") + VarDeclInitializer{}(*m_ast); else if (m_optimizerStep == "forLoopInitRewriter") { disambiguate(); diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul new file mode 100644 index 00000000..5e2d60c2 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul @@ -0,0 +1,29 @@ +{ + // This component does not need the disambiguator + function f() -> x, y { + let a, b + mstore(a, b) + let d + d := 2 + } + let a + a := 4 + let b := 2 + let x, y := f() +} +// ---- +// varDeclInitializer +// { +// function f() -> x, y +// { +// let a := 0 +// let b := 0 +// mstore(a, b) +// let d := 0 +// d := 2 +// } +// let a := 0 +// a := 4 +// let b := 2 +// let x, y := f() +// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul new file mode 100644 index 00000000..16428d7e --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul @@ -0,0 +1,24 @@ +{ + function f() -> x, y { + let a, b + mstore(a, b) + let d + d := 2 + } + let r + r := 4 +} +// ---- +// varDeclInitializer +// { +// function f() -> x, y +// { +// let a := 0 +// let b := 0 +// mstore(a, b) +// let d := 0 +// d := 2 +// } +// let r := 0 +// r := 4 +// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul new file mode 100644 index 00000000..02d731af --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul @@ -0,0 +1,14 @@ +{ + let x, y, z + let a + let b +} +// ---- +// varDeclInitializer +// { +// let x := 0 +// let y := 0 +// let z := 0 +// let a := 0 +// let b := 0 +// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul new file mode 100644 index 00000000..2e14fe70 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul @@ -0,0 +1,21 @@ +{ + function f() -> x, y { + let a, b := f() + let u + } + let r + let s := 3 + let t +} +// ---- +// varDeclInitializer +// { +// function f() -> x, y +// { +// let a, b := f() +// let u := 0 +// } +// let r := 0 +// let s := 3 +// let t := 0 +// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul new file mode 100644 index 00000000..2a9bbe42 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul @@ -0,0 +1,8 @@ +{ + let a +} +// ---- +// varDeclInitializer +// { +// let a := 0 +// } |