aboutsummaryrefslogtreecommitdiffstats
path: root/test/libyul
diff options
context:
space:
mode:
Diffstat (limited to 'test/libyul')
-rw-r--r--test/libyul/Common.cpp38
-rw-r--r--test/libyul/Common.h19
-rw-r--r--test/libyul/Inliner.cpp7
-rw-r--r--test/libyul/ObjectParser.cpp257
-rw-r--r--test/libyul/Parser.cpp29
-rw-r--r--test/libyul/YulOptimizerTest.cpp37
-rw-r--r--test/libyul/YulOptimizerTest.h22
-rw-r--r--test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul23
-rw-r--r--test/libyul/yulOptimizerTests/forLoopInitRewriter/empty_pre.yul20
-rw-r--r--test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul21
10 files changed, 398 insertions, 75 deletions
diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp
index d224bdcd..a247a169 100644
--- a/test/libyul/Common.cpp
+++ b/test/libyul/Common.cpp
@@ -23,24 +23,24 @@
#include <test/Options.h>
-#include <libyul/optimiser/Disambiguator.h>
-
-#include <libsolidity/parsing/Scanner.h>
+#include <liblangutil/SourceReferenceFormatter.h>
-#include <libsolidity/inlineasm/AsmParser.h>
-#include <libsolidity/inlineasm/AsmAnalysis.h>
-#include <libsolidity/inlineasm/AsmPrinter.h>
+#include <libyul/optimiser/Disambiguator.h>
+#include <libyul/AsmParser.h>
+#include <libyul/AsmAnalysis.h>
+#include <libyul/AsmPrinter.h>
-#include <libsolidity/interface/SourceReferenceFormatter.h>
-#include <libsolidity/interface/ErrorReporter.h>
+#include <liblangutil/Scanner.h>
+#include <liblangutil/ErrorReporter.h>
#include <boost/test/unit_test.hpp>
using namespace std;
-using namespace dev::yul;
+using namespace langutil;
+using namespace yul;
using namespace dev::solidity;
-void dev::yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner)
+void yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner)
{
SourceReferenceFormatter formatter(cout, [&](std::string const&) -> Scanner const& { return _scanner; });
@@ -52,18 +52,18 @@ void dev::yul::test::printErrors(ErrorList const& _errors, Scanner const& _scann
}
-pair<shared_ptr<Block>, shared_ptr<assembly::AsmAnalysisInfo>> dev::yul::test::parse(string const& _source, bool _yul)
+pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(string const& _source, bool _yul)
{
- auto flavour = _yul ? assembly::AsmFlavour::Yul : assembly::AsmFlavour::Strict;
+ auto flavour = _yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict;
ErrorList errors;
ErrorReporter errorReporter(errors);
- auto scanner = make_shared<Scanner>(CharStream(_source), "");
- auto parserResult = assembly::Parser(errorReporter, flavour).parse(scanner, false);
+ auto scanner = make_shared<Scanner>(CharStream(_source, ""));
+ auto parserResult = yul::Parser(errorReporter, flavour).parse(scanner, false);
if (parserResult)
{
BOOST_REQUIRE(errorReporter.errors().empty());
- auto analysisInfo = make_shared<assembly::AsmAnalysisInfo>();
- assembly::AsmAnalyzer analyzer(
+ auto analysisInfo = make_shared<yul::AsmAnalysisInfo>();
+ yul::AsmAnalyzer analyzer(
*analysisInfo,
errorReporter,
dev::test::Options::get().evmVersion(),
@@ -83,13 +83,13 @@ pair<shared_ptr<Block>, shared_ptr<assembly::AsmAnalysisInfo>> dev::yul::test::p
return {};
}
-assembly::Block dev::yul::test::disambiguate(string const& _source, bool _yul)
+yul::Block yul::test::disambiguate(string const& _source, bool _yul)
{
auto result = parse(_source, _yul);
return boost::get<Block>(Disambiguator(*result.second, {})(*result.first));
}
-string dev::yul::test::format(string const& _source, bool _yul)
+string yul::test::format(string const& _source, bool _yul)
{
- return assembly::AsmPrinter(_yul)(*parse(_source, _yul).first);
+ return yul::AsmPrinter(_yul)(*parse(_source, _yul).first);
}
diff --git a/test/libyul/Common.h b/test/libyul/Common.h
index ee191494..a1c64ca5 100644
--- a/test/libyul/Common.h
+++ b/test/libyul/Common.h
@@ -21,35 +21,34 @@
#pragma once
-#include <libsolidity/inlineasm/AsmData.h>
+#include <libyul/AsmData.h>
#include <string>
#include <vector>
#include <memory>
-namespace dev
-{
-namespace solidity
+namespace langutil
{
class Scanner;
class Error;
using ErrorList = std::vector<std::shared_ptr<Error const>>;
-namespace assembly
+}
+
+namespace yul
{
struct AsmAnalysisInfo;
}
-}
+
namespace yul
{
namespace test
{
-void printErrors(solidity::ErrorList const& _errors, solidity::Scanner const& _scanner);
-std::pair<std::shared_ptr<solidity::assembly::Block>, std::shared_ptr<solidity::assembly::AsmAnalysisInfo>>
+void printErrors(langutil::ErrorList const& _errors, langutil::Scanner const& _scanner);
+std::pair<std::shared_ptr<Block>, std::shared_ptr<AsmAnalysisInfo>>
parse(std::string const& _source, bool _yul = true);
-solidity::assembly::Block disambiguate(std::string const& _source, bool _yul = true);
+Block disambiguate(std::string const& _source, bool _yul = true);
std::string format(std::string const& _source, bool _yul = true);
}
}
-}
diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp
index 66810298..631cda08 100644
--- a/test/libyul/Inliner.cpp
+++ b/test/libyul/Inliner.cpp
@@ -26,8 +26,7 @@
#include <libyul/optimiser/FullInliner.h>
#include <libyul/optimiser/FunctionHoister.h>
#include <libyul/optimiser/FunctionGrouper.h>
-
-#include <libsolidity/inlineasm/AsmPrinter.h>
+#include <libyul/AsmPrinter.h>
#include <boost/test/unit_test.hpp>
@@ -36,8 +35,8 @@
using namespace std;
using namespace dev;
-using namespace dev::yul;
-using namespace dev::yul::test;
+using namespace yul;
+using namespace yul::test;
using namespace dev::solidity;
namespace
diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp
new file mode 100644
index 00000000..bb88e4da
--- /dev/null
+++ b/test/libyul/ObjectParser.cpp
@@ -0,0 +1,257 @@
+/*
+ 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/>.
+*/
+/**
+ * @date 2018
+ * Unit tests for the Yul object parser.
+ */
+
+#include <test/Options.h>
+
+#include <test/libsolidity/ErrorCheck.h>
+
+#include <libsolidity/interface/AssemblyStack.h>
+
+#include <boost/optional.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+#include <string>
+#include <memory>
+
+using namespace std;
+using namespace langutil;
+
+namespace dev
+{
+namespace yul
+{
+namespace test
+{
+
+namespace
+{
+
+std::pair<bool, ErrorList> parse(string const& _source)
+{
+ try
+ {
+ solidity::AssemblyStack asmStack(
+ dev::test::Options::get().evmVersion(),
+ solidity::AssemblyStack::Language::StrictAssembly
+ );
+ bool success = asmStack.parseAndAnalyze("source", _source);
+ return {success, asmStack.errors()};
+ }
+ catch (FatalError const&)
+ {
+ BOOST_FAIL("Fatal error leaked.");
+ }
+ return {false, {}};
+}
+
+boost::optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarnings = true)
+{
+ bool success;
+ ErrorList errors;
+ tie(success, errors) = parse(_source);
+ if (!success)
+ {
+ BOOST_REQUIRE_EQUAL(errors.size(), 1);
+ return *errors.front();
+ }
+ else
+ {
+ // If success is true, there might still be an error in the assembly stage.
+ if (_allowWarnings && Error::containsOnlyWarnings(errors))
+ return {};
+ else if (!errors.empty())
+ {
+ if (!_allowWarnings)
+ BOOST_CHECK_EQUAL(errors.size(), 1);
+ return *errors.front();
+ }
+ }
+ return {};
+}
+
+bool successParse(std::string const& _source, bool _allowWarnings = true)
+{
+ return !parseAndReturnFirstError(_source, _allowWarnings);
+}
+
+Error expectError(std::string const& _source, bool _allowWarnings = false)
+{
+
+ auto error = parseAndReturnFirstError(_source, _allowWarnings);
+ BOOST_REQUIRE(error);
+ return *error;
+}
+
+}
+
+#define CHECK_ERROR(text, typ, substring) \
+do \
+{ \
+ Error err = expectError((text), false); \
+ BOOST_CHECK(err.type() == (Error::Type::typ)); \
+ BOOST_CHECK(solidity::searchErrorMessage(err, (substring))); \
+} while(0)
+
+BOOST_AUTO_TEST_SUITE(YulObjectParser)
+
+BOOST_AUTO_TEST_CASE(empty_code)
+{
+ BOOST_CHECK(successParse("{ }"));
+}
+
+BOOST_AUTO_TEST_CASE(object_with_empty_code)
+{
+ BOOST_CHECK(successParse("object \"a\" { code { } }"));
+}
+
+BOOST_AUTO_TEST_CASE(non_object)
+{
+ CHECK_ERROR("code {}", ParserError, "Expected keyword \"object\"");
+}
+
+BOOST_AUTO_TEST_CASE(empty_name)
+{
+ CHECK_ERROR("object \"\" { code {} }", ParserError, "Object name cannot be empty");
+}
+
+BOOST_AUTO_TEST_CASE(recursion_depth)
+{
+ string input;
+ for (size_t i = 0; i < 20000; i++)
+ input += "object \"a" + to_string(i) + "\" { code {} ";
+ for (size_t i = 0; i < 20000; i++)
+ input += "}";
+
+ CHECK_ERROR(input, ParserError, "recursion");
+}
+
+BOOST_AUTO_TEST_CASE(object_with_code)
+{
+ BOOST_CHECK(successParse("object \"a\" { code { let x := mload(0) sstore(0, x) } }"));
+}
+
+BOOST_AUTO_TEST_CASE(object_with_code_and_data)
+{
+ BOOST_CHECK(successParse("object \"a\" { code { let x := mload(0) sstore(0, x) } data \"b\" hex\"01010202\" }"));
+}
+
+BOOST_AUTO_TEST_CASE(object_with_non_code_at_start)
+{
+ CHECK_ERROR("object \"a\" { data \"d\" hex\"0102\" code { } }", ParserError, "Expected keyword \"code\"");
+}
+
+BOOST_AUTO_TEST_CASE(nested_object)
+{
+ string code = R"(
+ object "outer" {
+ code { let x := mload(0) }
+ data "x" "stringdata"
+ object "inner" {
+ code { mstore(0, 1) }
+ object "inner inner" { code {} }
+ data "innerx" "abc"
+ data "innery" "def"
+ }
+ }
+ )";
+ BOOST_CHECK(successParse(code));
+}
+
+BOOST_AUTO_TEST_CASE(incomplete)
+{
+ CHECK_ERROR("object \"abc\" { code {} } object", ParserError, "Expected end of source");
+}
+
+BOOST_AUTO_TEST_CASE(reuse_object_name)
+{
+ string code = R"(
+ object "outer" {
+ code { }
+ data "outer" "stringdata"
+ }
+ )";
+ CHECK_ERROR(code, ParserError, "Object name cannot be the same as the name of the containing object");
+}
+
+BOOST_AUTO_TEST_CASE(reuse_object_in_subobject)
+{
+ string code = R"(
+ object "outer" {
+ code { }
+ object "outer" { code {} }
+ }
+ )";
+ CHECK_ERROR(code, ParserError, "Object name cannot be the same as the name of the containing object");
+}
+
+BOOST_AUTO_TEST_CASE(reuse_object_of_sibling)
+{
+ string code = R"(
+ object "O" {
+ code { }
+ object "i" { code {} }
+ data "i" "abc"
+ }
+ )";
+ CHECK_ERROR(code, ParserError, "already exists inside the");
+}
+
+BOOST_AUTO_TEST_CASE(to_string)
+{
+ string code = R"(
+ object "O" {
+ code { let x := mload(0) if x { sstore(0, 1) } }
+ object "i" { code {} data "j" "def" }
+ data "j" "abc"
+ data "k" hex"010203"
+ }
+ )";
+ string expectation = R"(object "O" {
+ code {
+ let x := mload(0)
+ if x
+ {
+ sstore(0, 1)
+ }
+ }
+ object "i" {
+ code {
+ }
+ data "j" hex"646566"
+ }
+ data "j" hex"616263"
+ data "k" hex"010203"
+}
+)";
+ expectation = boost::replace_all_copy(expectation, "\t", " ");
+ solidity::AssemblyStack asmStack(
+ dev::test::Options::get().evmVersion(),
+ solidity::AssemblyStack::Language::StrictAssembly
+ );
+ BOOST_REQUIRE(asmStack.parseAndAnalyze("source", code));
+ BOOST_CHECK_EQUAL(asmStack.print(), expectation);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+} // end namespaces
diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp
index 3f329d28..caaf2719 100644
--- a/test/libyul/Parser.cpp
+++ b/test/libyul/Parser.cpp
@@ -23,11 +23,11 @@
#include <test/libsolidity/ErrorCheck.h>
-#include <libsolidity/inlineasm/AsmParser.h>
-#include <libsolidity/inlineasm/AsmAnalysis.h>
-#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
-#include <libsolidity/parsing/Scanner.h>
-#include <libsolidity/interface/ErrorReporter.h>
+#include <libyul/AsmParser.h>
+#include <libyul/AsmAnalysis.h>
+#include <libyul/AsmAnalysisInfo.h>
+#include <liblangutil/Scanner.h>
+#include <liblangutil/ErrorReporter.h>
#include <boost/optional.hpp>
#include <boost/algorithm/string/replace.hpp>
@@ -36,10 +36,10 @@
#include <memory>
using namespace std;
+using namespace dev;
+using namespace langutil;
-namespace dev
-{
-namespace solidity
+namespace yul
{
namespace test
{
@@ -51,17 +51,17 @@ bool parse(string const& _source, ErrorReporter& errorReporter)
{
try
{
- auto scanner = make_shared<Scanner>(CharStream(_source));
- auto parserResult = assembly::Parser(errorReporter, assembly::AsmFlavour::Yul).parse(scanner, false);
+ auto scanner = make_shared<Scanner>(CharStream(_source, ""));
+ auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Yul).parse(scanner, false);
if (parserResult)
{
- assembly::AsmAnalysisInfo analysisInfo;
- return (assembly::AsmAnalyzer(
+ yul::AsmAnalysisInfo analysisInfo;
+ return (yul::AsmAnalyzer(
analysisInfo,
errorReporter,
dev::test::Options::get().evmVersion(),
boost::none,
- assembly::AsmFlavour::Yul
+ yul::AsmFlavour::Yul
)).analyze(*parserResult);
}
}
@@ -116,7 +116,7 @@ do \
{ \
Error err = expectError((text), false); \
BOOST_CHECK(err.type() == (Error::Type::typ)); \
- BOOST_CHECK(searchErrorMessage(err, (substring))); \
+ BOOST_CHECK(dev::solidity::searchErrorMessage(err, (substring))); \
} while(0)
BOOST_AUTO_TEST_SUITE(YulParser)
@@ -302,5 +302,4 @@ BOOST_AUTO_TEST_CASE(if_statement_invalid)
BOOST_AUTO_TEST_SUITE_END()
}
-}
} // end namespaces
diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp
index 03cd6446..15d70faa 100644
--- a/test/libyul/YulOptimizerTest.cpp
+++ b/test/libyul/YulOptimizerTest.cpp
@@ -31,6 +31,7 @@
#include <libyul/optimiser/FunctionHoister.h>
#include <libyul/optimiser/ExpressionInliner.h>
#include <libyul/optimiser/FullInliner.h>
+#include <libyul/optimiser/ForLoopInitRewriter.h>
#include <libyul/optimiser/MainFunction.h>
#include <libyul/optimiser/Rematerialiser.h>
#include <libyul/optimiser/ExpressionSimplifier.h>
@@ -39,13 +40,13 @@
#include <libyul/optimiser/SSATransform.h>
#include <libyul/optimiser/RedundantAssignEliminator.h>
#include <libyul/optimiser/Suite.h>
+#include <libyul/AsmPrinter.h>
+#include <libyul/AsmParser.h>
+#include <libyul/AsmAnalysis.h>
+#include <liblangutil/SourceReferenceFormatter.h>
-#include <libsolidity/parsing/Scanner.h>
-#include <libsolidity/inlineasm/AsmPrinter.h>
-#include <libsolidity/inlineasm/AsmParser.h>
-#include <libsolidity/inlineasm/AsmAnalysis.h>
-#include <libsolidity/interface/SourceReferenceFormatter.h>
-#include <libsolidity/interface/ErrorReporter.h>
+#include <liblangutil/ErrorReporter.h>
+#include <liblangutil/Scanner.h>
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string.hpp>
@@ -53,8 +54,9 @@
#include <fstream>
using namespace dev;
-using namespace dev::yul;
-using namespace dev::yul::test;
+using namespace langutil;
+using namespace yul;
+using namespace yul::test;
using namespace dev::solidity;
using namespace dev::solidity::test;
using namespace std;
@@ -90,9 +92,9 @@ YulOptimizerTest::YulOptimizerTest(string const& _filename)
bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted)
{
- assembly::AsmPrinter printer{m_yul};
+ yul::AsmPrinter printer{m_yul};
shared_ptr<Block> ast;
- shared_ptr<assembly::AsmAnalysisInfo> analysisInfo;
+ shared_ptr<yul::AsmAnalysisInfo> analysisInfo;
if (!parse(_stream, _linePrefix, _formatted))
return false;
@@ -108,6 +110,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
disambiguate();
VarDeclPropagator{}(*m_ast);
}
+ else if (m_optimizerStep == "forLoopInitRewriter")
+ {
+ disambiguate();
+ ForLoopInitRewriter{}(*m_ast);
+ }
else if (m_optimizerStep == "commonSubexpressionEliminator")
{
disambiguate();
@@ -249,19 +256,19 @@ void YulOptimizerTest::printIndented(ostream& _stream, string const& _output, st
bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted)
{
- assembly::AsmFlavour flavour = m_yul ? assembly::AsmFlavour::Yul : assembly::AsmFlavour::Strict;
+ yul::AsmFlavour flavour = m_yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict;
ErrorList errors;
ErrorReporter errorReporter(errors);
- shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source), "");
- m_ast = assembly::Parser(errorReporter, flavour).parse(scanner, false);
+ shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source, ""));
+ m_ast = yul::Parser(errorReporter, flavour).parse(scanner, false);
if (!m_ast || !errorReporter.errors().empty())
{
FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl;
printErrors(_stream, errorReporter.errors(), *scanner);
return false;
}
- m_analysisInfo = make_shared<assembly::AsmAnalysisInfo>();
- assembly::AsmAnalyzer analyzer(
+ m_analysisInfo = make_shared<yul::AsmAnalysisInfo>();
+ yul::AsmAnalyzer analyzer(
*m_analysisInfo,
errorReporter,
dev::test::Options::get().evmVersion(),
diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h
index 7db17ceb..90026e24 100644
--- a/test/libyul/YulOptimizerTest.h
+++ b/test/libyul/YulOptimizerTest.h
@@ -17,28 +17,27 @@
#pragma once
-#include <test/libsolidity/TestCase.h>
+#include <test/TestCase.h>
-
-namespace dev
-{
-namespace solidity
+namespace langutil
{
class Scanner;
class Error;
using ErrorList = std::vector<std::shared_ptr<Error const>>;
-namespace assembly
+}
+
+namespace yul
{
struct AsmAnalysisInfo;
struct Block;
}
-}
+
namespace yul
{
namespace test
{
-class YulOptimizerTest: public solidity::test::TestCase
+class YulOptimizerTest: public dev::solidity::test::TestCase
{
public:
static std::unique_ptr<TestCase> create(std::string const& _filename)
@@ -58,18 +57,17 @@ private:
bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted);
void disambiguate();
- static void printErrors(std::ostream& _stream, solidity::ErrorList const& _errors, solidity::Scanner const& _scanner);
+ static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors, langutil::Scanner const& _scanner);
std::string m_source;
bool m_yul = false;
std::string m_optimizerStep;
std::string m_expectation;
- std::shared_ptr<solidity::assembly::Block> m_ast;
- std::shared_ptr<solidity::assembly::AsmAnalysisInfo> m_analysisInfo;
+ std::shared_ptr<Block> m_ast;
+ std::shared_ptr<AsmAnalysisInfo> m_analysisInfo;
std::string m_obtainedResult;
};
}
}
-}
diff --git a/test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul b/test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul
new file mode 100644
index 00000000..3ca00f55
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul
@@ -0,0 +1,23 @@
+{
+ let random := 42
+ for { let a := 1
+ let b := 1 } iszero(eq(a, 10)) { a := add(a, b) } {
+ a := add(a, 1)
+ }
+}
+// ----
+// forLoopInitRewriter
+// {
+// let random := 42
+// let a := 1
+// let b := 1
+// for {
+// }
+// iszero(eq(a, 10))
+// {
+// a := add(a, b)
+// }
+// {
+// a := add(a, 1)
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/forLoopInitRewriter/empty_pre.yul b/test/libyul/yulOptimizerTests/forLoopInitRewriter/empty_pre.yul
new file mode 100644
index 00000000..05aceb52
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/forLoopInitRewriter/empty_pre.yul
@@ -0,0 +1,20 @@
+{
+ let a := 1
+ for {} iszero(eq(a, 10)) { a := add(a, 1) } {
+ a := add(a, 1)
+ }
+}
+// ----
+// forLoopInitRewriter
+// {
+// let a := 1
+// for {
+// }
+// iszero(eq(a, 10))
+// {
+// a := add(a, 1)
+// }
+// {
+// a := add(a, 1)
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul b/test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul
new file mode 100644
index 00000000..565b7725
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul
@@ -0,0 +1,21 @@
+{
+ let random := 42
+ for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } {
+ a := add(a, 1)
+ }
+}
+// ----
+// forLoopInitRewriter
+// {
+// let random := 42
+// let a := 1
+// for {
+// }
+// iszero(eq(a, 10))
+// {
+// a := add(a, 1)
+// }
+// {
+// a := add(a, 1)
+// }
+// }