CommandLineParser: Store the state of EVM assembly and Yul optimizer explicitly

- Does not change the meaning of CLI options, just the way we map them to internal variables.
This commit is contained in:
Kamil Śliwak 2023-05-24 14:22:18 +02:00
parent f1d2eda795
commit 42a068b449
5 changed files with 48 additions and 14 deletions

View File

@ -1074,9 +1074,6 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
map<string, yul::YulStack> yulStacks; map<string, yul::YulStack> yulStacks;
for (auto const& src: m_fileReader.sourceUnits()) for (auto const& src: m_fileReader.sourceUnits())
{ {
// --no-optimize-yul option is not accepted in assembly mode.
solAssert(!m_options.optimizer.noOptimizeYul);
auto& stack = yulStacks[src.first] = yul::YulStack( auto& stack = yulStacks[src.first] = yul::YulStack(
m_options.output.evmVersion, m_options.output.evmVersion,
m_options.output.eofVersion, m_options.output.eofVersion,

View File

@ -247,9 +247,9 @@ bool CommandLineOptions::operator==(CommandLineOptions const& _other) const noex
metadata.format == _other.metadata.format && metadata.format == _other.metadata.format &&
metadata.hash == _other.metadata.hash && metadata.hash == _other.metadata.hash &&
metadata.literalSources == _other.metadata.literalSources && metadata.literalSources == _other.metadata.literalSources &&
optimizer.enabled == _other.optimizer.enabled && optimizer.optimizeEvmasm == _other.optimizer.optimizeEvmasm &&
optimizer.optimizeYul == _other.optimizer.optimizeYul &&
optimizer.expectedExecutionsPerDeployment == _other.optimizer.expectedExecutionsPerDeployment && optimizer.expectedExecutionsPerDeployment == _other.optimizer.expectedExecutionsPerDeployment &&
optimizer.noOptimizeYul == _other.optimizer.noOptimizeYul &&
optimizer.yulSteps == _other.optimizer.yulSteps && optimizer.yulSteps == _other.optimizer.yulSteps &&
modelChecker.initialize == _other.modelChecker.initialize && modelChecker.initialize == _other.modelChecker.initialize &&
modelChecker.settings == _other.modelChecker.settings; modelChecker.settings == _other.modelChecker.settings;
@ -259,12 +259,12 @@ OptimiserSettings CommandLineOptions::optimiserSettings() const
{ {
OptimiserSettings settings; OptimiserSettings settings;
if (optimizer.enabled) if (optimizer.optimizeEvmasm || optimizer.optimizeYul)
settings = OptimiserSettings::standard(); settings = OptimiserSettings::standard();
else else
settings = OptimiserSettings::minimal(); settings = OptimiserSettings::minimal();
if (optimizer.noOptimizeYul) if (!optimizer.optimizeYul)
settings.runYulOptimiser = false; settings.runYulOptimiser = false;
if (optimizer.expectedExecutionsPerDeployment.has_value()) if (optimizer.expectedExecutionsPerDeployment.has_value())
@ -1166,8 +1166,10 @@ void CommandLineParser::processArgs()
); );
// We deliberately ignore --optimize-yul // We deliberately ignore --optimize-yul
m_options.optimizer.enabled = (m_args.count(g_strOptimize) > 0); m_options.optimizer.optimizeEvmasm = (m_args.count(g_strOptimize) > 0);
m_options.optimizer.noOptimizeYul = (m_args.count(g_strNoOptimizeYul) > 0); m_options.optimizer.optimizeYul = (
m_args.count(g_strOptimize) > 0 && m_args.count(g_strNoOptimizeYul) == 0
);
if (!m_args[g_strOptimizeRuns].defaulted()) if (!m_args[g_strOptimizeRuns].defaulted())
m_options.optimizer.expectedExecutionsPerDeployment = m_args.at(g_strOptimizeRuns).as<unsigned>(); m_options.optimizer.expectedExecutionsPerDeployment = m_args.at(g_strOptimizeRuns).as<unsigned>();
@ -1235,7 +1237,10 @@ void CommandLineParser::processArgs()
else else
solThrow(CommandLineValidationError, "Invalid option for --" + g_strYulDialect + ": " + dialect); solThrow(CommandLineValidationError, "Invalid option for --" + g_strYulDialect + ": " + dialect);
} }
if (m_options.optimizer.enabled && (m_options.assembly.inputLanguage != Input::StrictAssembly)) if (
(m_options.optimizer.optimizeEvmasm || m_options.optimizer.optimizeYul) &&
m_options.assembly.inputLanguage != Input::StrictAssembly
)
solThrow( solThrow(
CommandLineValidationError, CommandLineValidationError,
"Optimizer can only be used for strict assembly. Use --" + g_strStrictAssembly + "." "Optimizer can only be used for strict assembly. Use --" + g_strStrictAssembly + "."

View File

@ -223,9 +223,9 @@ struct CommandLineOptions
struct struct
{ {
bool enabled = false; bool optimizeEvmasm = false;
bool optimizeYul = false;
std::optional<unsigned> expectedExecutionsPerDeployment; std::optional<unsigned> expectedExecutionsPerDeployment;
bool noOptimizeYul = false;
std::optional<std::string> yulSteps; std::optional<std::string> yulSteps;
} optimizer; } optimizer;

View File

@ -140,6 +140,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
"--metadata-hash=swarm", "--metadata-hash=swarm",
"--metadata-literal", "--metadata-literal",
"--optimize", "--optimize",
"--optimize-yul",
"--optimize-runs=1000", "--optimize-runs=1000",
"--yul-optimizations=agf", "--yul-optimizations=agf",
"--model-checker-bmc-loop-iterations=2", "--model-checker-bmc-loop-iterations=2",
@ -205,7 +206,8 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
}; };
expectedOptions.metadata.hash = CompilerStack::MetadataHash::Bzzr1; expectedOptions.metadata.hash = CompilerStack::MetadataHash::Bzzr1;
expectedOptions.metadata.literalSources = true; expectedOptions.metadata.literalSources = true;
expectedOptions.optimizer.enabled = true; expectedOptions.optimizer.optimizeEvmasm = true;
expectedOptions.optimizer.optimizeYul = true;
expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000; expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000;
expectedOptions.optimizer.yulSteps = "agf"; expectedOptions.optimizer.yulSteps = "agf";
@ -336,7 +338,8 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options)
expectedOptions.compiler.outputs.astCompactJson = true; expectedOptions.compiler.outputs.astCompactJson = true;
if (expectedLanguage == YulStack::Language::StrictAssembly) if (expectedLanguage == YulStack::Language::StrictAssembly)
{ {
expectedOptions.optimizer.enabled = true; expectedOptions.optimizer.optimizeEvmasm = true;
expectedOptions.optimizer.optimizeYul = true;
expectedOptions.optimizer.yulSteps = "agf"; expectedOptions.optimizer.yulSteps = "agf";
expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000; expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000;
} }
@ -435,6 +438,34 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations)
} }
} }
BOOST_AUTO_TEST_CASE(optimizer_flags)
{
OptimiserSettings evmasmOnly = OptimiserSettings::standard();
evmasmOnly.runYulOptimiser = false;
map<vector<string>, OptimiserSettings> settingsMap = {
{{}, OptimiserSettings::minimal()},
{{"--optimize"}, OptimiserSettings::standard()},
{{"--no-optimize-yul"}, OptimiserSettings::minimal()},
{{"--optimize-yul"}, OptimiserSettings::minimal()},
{{"--optimize", "--no-optimize-yul"}, evmasmOnly},
{{"--optimize", "--optimize-yul"}, OptimiserSettings::standard()},
};
map<InputMode, string> inputModeFlagMap = {
{InputMode::Compiler, ""},
{InputMode::CompilerWithASTImport, "--import-ast"},
};
for (auto const& [inputMode, inputModeFlag]: inputModeFlagMap)
for (auto const& [optimizerFlags, expectedOptimizerSettings]: settingsMap)
{
vector<string> commandLine = {"solc", inputModeFlag, "file"};
commandLine += optimizerFlags;
BOOST_CHECK(parseCommandLine(commandLine).optimiserSettings() == expectedOptimizerSettings);
}
}
BOOST_AUTO_TEST_CASE(default_optimiser_sequence) BOOST_AUTO_TEST_CASE(default_optimiser_sequence)
{ {
CommandLineOptions const& commandLineOptions = parseCommandLine({"solc", "contract.sol", "--optimize"}); CommandLineOptions const& commandLineOptions = parseCommandLine({"solc", "contract.sol", "--optimize"});

View File

@ -28,6 +28,7 @@
BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::CommandLineOptions) BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::CommandLineOptions)
BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::InputMode) BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::InputMode)
BOOST_TEST_DONT_PRINT_LOG_VALUE(solidity::frontend::OptimiserSettings)
namespace solidity::frontend::test namespace solidity::frontend::test
{ {