Skip to content

Commit

Permalink
Kamil
Browse files Browse the repository at this point in the history
  • Loading branch information
nikola-matic committed Nov 2, 2023
1 parent 2a022ff commit b44e88d
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 70 deletions.
33 changes: 11 additions & 22 deletions libsolidity/interface/StandardCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ std::optional<Json::Value> checkOptimizerDetail(Json::Value const& _details, std
return {};
}

std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details, std::string const& _name, std::string& _optimiserSetting, std::string& _cleanupSetting)
std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details, std::string const& _name, std::string& _optimiserSetting, std::string& _cleanupSetting, bool _runYulOptimizer)
{
if (_details.isMember(_name))
{
Expand All @@ -482,6 +482,9 @@ std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details
_cleanupSetting = fullSequence.substr(delimiterPos + 1);
else
solAssert(_cleanupSetting == OptimiserSettings::DefaultYulOptimiserCleanupSteps);

if (!_runYulOptimizer && OptimiserSuite::isEmptyOptimizerSequence(fullSequence))
return formatFatalError(Error::Type::JSONError, "If Yul optimizer is disabled, only an empty optimizerSteps sequence is accepted.");
}
else
return formatFatalError(Error::Type::JSONError, "\"settings.optimizer.details." + _name + "\" must be a string");
Expand Down Expand Up @@ -606,36 +609,22 @@ std::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Value
{
if (!settings.runYulOptimiser)
{
auto const& yulDetails = details["yulDetails"];
if (yulDetails.isObject() && yulDetails.isMember("optimizerSteps"))
{
auto error = checkOptimizerDetailSteps(details["yulDetails"], "optimizerSteps", settings.yulOptimiserSteps, settings.yulOptimiserCleanupSteps);
auto isWhiteSpaceOrNewlineOnly = [](std::string const& _sequence) {
return !std::any_of(_sequence.begin(), _sequence.end(), [](char const step){
return step != ' ' && step != '\n';
});
};
if (
!error &&
isWhiteSpaceOrNewlineOnly(settings.yulOptimiserSteps) &&
isWhiteSpaceOrNewlineOnly(settings.yulOptimiserCleanupSteps)
)
return { std::move(settings) };
else
return formatFatalError(Error::Type::JSONError, "\"If Yul optimizer is disabled, only an empty optimizerSteps sequence (\":\") is accepted.\"");
}
return formatFatalError(Error::Type::JSONError, "\"Providing yulDetails requires Yul optimizer to be enabled.");
if (checkKeys(details["yulDetails"], {"optimizerSteps"}, "settings.optimizer.details.yulDetails"))
return formatFatalError(Error::Type::JSONError, "Only optimizerSteps can be set in yulDetails when Yul optimizer is disabled.");
if (auto error = checkOptimizerDetailSteps(details["yulDetails"], "optimizerSteps", settings.yulOptimiserSteps, settings.yulOptimiserCleanupSteps, settings.runYulOptimiser))
*error;
return {std::move(settings)};
}

if (auto result = checkKeys(details["yulDetails"], {"stackAllocation", "optimizerSteps"}, "settings.optimizer.details.yulDetails"))
return *result;
if (auto error = checkOptimizerDetail(details["yulDetails"], "stackAllocation", settings.optimizeStackAllocation))
return *error;
if (auto error = checkOptimizerDetailSteps(details["yulDetails"], "optimizerSteps", settings.yulOptimiserSteps, settings.yulOptimiserCleanupSteps))
if (auto error = checkOptimizerDetailSteps(details["yulDetails"], "optimizerSteps", settings.yulOptimiserSteps, settings.yulOptimiserCleanupSteps, settings.runYulOptimiser))
return *error;
}
}
return { std::move(settings) };
return {std::move(settings)};
}

}
Expand Down
11 changes: 10 additions & 1 deletion libyul/YulStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@
#include <libyul/optimiser/Suite.h>
#include <libevmasm/Assembly.h>
#include <liblangutil/Scanner.h>
#include <libsolidity/interface/OptimiserSettings.h>

#include <boost/algorithm/string.hpp>

#include <optional>

using namespace solidity;
using namespace solidity::frontend;
using namespace solidity::yul;
using namespace solidity::langutil;

Expand Down Expand Up @@ -169,11 +171,18 @@ void YulStack::optimize(Object& _object, bool _isCreation)
if (!m_optimiserSettings.runYulOptimiser)
{
// Yul optimizer disabled, but empty sequence (:) explicitly provided
if (m_optimiserSettings.yulOptimiserSteps.empty() && m_optimiserSettings.yulOptimiserCleanupSteps.empty())
if (OptimiserSuite::isEmptyOptimizerSequence(m_optimiserSettings.yulOptimiserSteps + ":" + m_optimiserSettings.yulOptimiserCleanupSteps))
return std::make_tuple(true, "", "");
// Yul optimizer disabled, and no sequence explicitly provided (assumes default sequence)
else
{
yulAssert(
m_optimiserSettings.yulOptimiserSteps == OptimiserSettings::DefaultYulOptimiserSteps &&
m_optimiserSettings.yulOptimiserCleanupSteps == OptimiserSettings::DefaultYulOptimiserCleanupSteps
);
return std::make_tuple(true, "u", "");
}

}
return std::make_tuple(
m_optimiserSettings.optimizeStackAllocation,
Expand Down
18 changes: 18 additions & 0 deletions libyul/optimiser/Suite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,24 @@ void OptimiserSuite::validateSequence(std::string_view _stepAbbreviations)
assertThrow(nestingLevel == 0, OptimizerException, "Unbalanced brackets");
}

bool OptimiserSuite::isEmptyOptimizerSequence(std::string const& _sequence)
{
size_t delimiterCount{0};
for (char const step: _sequence)
switch (step)
{
case ':':
++delimiterCount;
break;
case ' ':
case '\n':
break;
default:
return false;
}
return delimiterCount == 1;
}

void OptimiserSuite::runSequence(std::string_view _stepAbbreviations, Block& _ast, bool _repeatUntilStable)
{
validateSequence(_stepAbbreviations);
Expand Down
4 changes: 4 additions & 0 deletions libyul/optimiser/Suite.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ class OptimiserSuite
/// Ensures that specified sequence of step abbreviations is well-formed and can be executed.
/// @throw OptimizerException if the sequence is invalid
static void validateSequence(std::string_view _stepAbbreviations);
/// Check whether the provided sequence is empty provided that the allowed characters are
/// whitespace, newline and :
static bool isEmptyOptimizerSequence(std::string const& _sequence);


void runSequence(std::vector<std::string> const& _steps, Block& _ast);
void runSequence(std::string_view _stepAbbreviations, Block& _ast, bool _repeatUntilStable = false);
Expand Down
23 changes: 3 additions & 20 deletions solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <fmt/format.h>

using namespace solidity::langutil;
using namespace solidity::yul;

namespace po = boost::program_options;

Expand Down Expand Up @@ -1228,8 +1229,8 @@ void CommandLineParser::processArgs()
if (m_args.count(g_strYulOptimizations))
{
OptimiserSettings optimiserSettings = m_options.optimiserSettings();
if (!optimiserSettings.runYulOptimiser && !isEmptyOptimizerSequence(m_args[g_strYulOptimizations].as<std::string>()))
solThrow(CommandLineValidationError, "--" + g_strYulOptimizations + " is invalid with any sequence other than empty (:) if Yul optimizer is disabled.");
if (!optimiserSettings.runYulOptimiser && !OptimiserSuite::isEmptyOptimizerSequence(m_args[g_strYulOptimizations].as<std::string>()))
solThrow(CommandLineValidationError, "--" + g_strYulOptimizations + " is invalid with a non-empty sequence if Yul optimizer is disabled.");

try
{
Expand Down Expand Up @@ -1485,24 +1486,6 @@ size_t CommandLineParser::countEnabledOptions(std::vector<std::string> const& _o
return count;
}

bool CommandLineParser::isEmptyOptimizerSequence(std::string const& _sequence) const
{
size_t delimiterCount{0};
for (char const step: _sequence)
switch (step)
{
case ':':
++delimiterCount;
break;
case ' ':
case '\n':
break;
default:
return false;
}
return delimiterCount == 1;
}

std::string CommandLineParser::joinOptionNames(std::vector<std::string> const& _optionNames, std::string _separator)
{
return util::joinHumanReadable(
Expand Down
1 change: 0 additions & 1 deletion solc/CommandLineParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ class CommandLineParser

void checkMutuallyExclusive(std::vector<std::string> const& _optionNames);
size_t countEnabledOptions(std::vector<std::string> const& _optionNames) const;
bool isEmptyOptimizerSequence(std::string const& _sequence) const;
static std::string joinOptionNames(std::vector<std::string> const& _optionNames, std::string _separator = ", ");

CommandLineOptions m_options;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
{
"errors":
[
"sources":
{
"A":
{
"component": "general",
"formattedMessage": "\"If Yul optimizer is disabled, only an empty optimizerSteps sequence (\":\") is accepted.\"",
"message": "\"If Yul optimizer is disabled, only an empty optimizerSteps sequence (\":\") is accepted.\"",
"severity": "error",
"type": "JSONError"
"id": 0
}
]
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"language": "Solidity",
"sources": {
"A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/in.sol"]}
},
"settings": {
"optimizer": {
"details": {
"yul": false,
"yulDetails": {
"optimizerSteps": ":"
}
}
}
}
"language": "Solidity",
"sources": {
"A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/in.sol"]}
},
"settings": {
"optimizer": {
"details": {
"yul": false,
"yulDetails": {
"optimizerSteps": ":"
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
[
{
"component": "general",
"formattedMessage": "\"Providing yulDetails requires Yul optimizer to be enabled.",
"message": "\"Providing yulDetails requires Yul optimizer to be enabled.",
"formattedMessage": "Only optimizerSteps can be set in yulDetails when Yul optimizer is disabled.",
"message": "Only optimizerSteps can be set in yulDetails when Yul optimizer is disabled.",
"severity": "error",
"type": "JSONError"
}
Expand Down
2 changes: 1 addition & 1 deletion test/cmdlineTests/yul_optimizer_steps_disabled/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Error: --yul-optimizations is invalid with any sequence other than empty (:) if Yul optimizer is disabled.
Error: --yul-optimizations is invalid with a non-empty sequence if Yul optimizer is disabled.
2 changes: 1 addition & 1 deletion test/solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ BOOST_AUTO_TEST_CASE(valid_empty_optimizer_sequences_without_optimize)
BOOST_AUTO_TEST_CASE(invalid_optimizer_sequence_without_optimize)
{
string const invalidSequence{"u: "};
string const expectedErrorMessage{"--yul-optimizations is invalid with any sequence other than empty (:) if Yul optimizer is disabled."};
string const expectedErrorMessage{"--yul-optimizations is invalid with a non-empty sequence if Yul optimizer is disabled."};
vector<string> commandLineOptions{"solc", "contract.sol", "--yul-optimizations=" + invalidSequence};
auto hasCorrectMessage = [&](CommandLineValidationError const& _exception) { return _exception.what() == expectedErrorMessage; };
BOOST_CHECK_EXCEPTION(parseCommandLine(commandLineOptions), CommandLineValidationError, hasCorrectMessage);
Expand Down

0 comments on commit b44e88d

Please sign in to comment.