Add yulDetails.optimizerSteps to the standard JSON interface

This commit is contained in:
Kamil Śliwak 2020-04-24 14:26:31 +02:00
parent 35cc64e33d
commit c8b612536f
13 changed files with 151 additions and 2 deletions

View File

@ -1265,6 +1265,7 @@ string CompilerStack::createMetadata(Contract const& _contract) const
{
details["yulDetails"] = Json::objectValue;
details["yulDetails"]["stackAllocation"] = m_optimiserSettings.optimizeStackAllocation;
details["yulDetails"]["optimizerSteps"] = m_optimiserSettings.yulOptimiserSteps;
}
meta["settings"]["optimizer"]["details"] = std::move(details);

View File

@ -25,6 +25,7 @@
#include <libsolidity/ast/ASTJsonConverter.h>
#include <libyul/AssemblyStack.h>
#include <libyul/Exceptions.h>
#include <libyul/optimiser/Suite.h>
#include <liblangutil/SourceReferenceFormatter.h>
#include <libevmasm/Instruction.h>
#include <libsolutil/JSON.h>
@ -402,6 +403,33 @@ std::optional<Json::Value> checkOptimizerDetail(Json::Value const& _details, std
return {};
}
std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details, std::string const& _name, string& _setting)
{
if (_details.isMember(_name))
{
if (_details[_name].isString())
{
try
{
yul::OptimiserSuite::validateSequence(_details[_name].asString());
}
catch (yul::OptimizerException const& _exception)
{
return formatFatalError(
"JSONError",
"Invalid optimizer step sequence in \"settings.optimizer.details." + _name + "\": " + _exception.what()
);
}
_setting = _details[_name].asString();
}
else
return formatFatalError("JSONError", "\"settings.optimizer.details." + _name + "\" must be a string");
}
return {};
}
std::optional<Json::Value> checkMetadataKeys(Json::Value const& _input)
{
if (_input.isObject())
@ -511,10 +539,12 @@ boost::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Valu
if (!settings.runYulOptimiser)
return formatFatalError("JSONError", "\"Providing yulDetails requires Yul optimizer to be enabled.");
if (auto result = checkKeys(details["yulDetails"], {"stackAllocation"}, "settings.optimizer.details.yulDetails"))
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))
return *error;
}
}
return { std::move(settings) };

View File

@ -0,0 +1,21 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
}
},
"settings":
{
"optimizer": {
"details": {
"yul": true,
"yulDetails": {
"optimizerSteps": "dhfoDgvulfnTUtnIf\n[ xarrscLM\n]\njmuljuljul VcTOcul jmul"
}
}
}
}
}

View File

@ -0,0 +1 @@
{"sources":{"A":{"id":0}}}

View File

@ -0,0 +1,21 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
}
},
"settings":
{
"optimizer": {
"details": {
"yul": true,
"yulDetails": {
"optimizerSteps": "abcdefg{hijklmno}pqr[st]uvwxyz"
}
}
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": 'b' is not a valid step abbreviation","message":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": 'b' is not a valid step abbreviation","severity":"error","type":"JSONError"}]}

View File

@ -0,0 +1,21 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
}
},
"settings":
{
"optimizer": {
"details": {
"yul": true,
"yulDetails": {
"optimizerSteps": "a[a][aa[aa]]a"
}
}
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Nested brackets are not supported","message":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Nested brackets are not supported","severity":"error","type":"JSONError"}]}

View File

@ -0,0 +1,21 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
}
},
"settings":
{
"optimizer": {
"details": {
"yul": true,
"yulDetails": {
"optimizerSteps": 42
}
}
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"\"settings.optimizer.details.optimizerSteps\" must be a string","message":"\"settings.optimizer.details.optimizerSteps\" must be a string","severity":"error","type":"JSONError"}]}

View File

@ -0,0 +1,21 @@
{
"language": "Solidity",
"sources":
{
"A":
{
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
}
},
"settings":
{
"optimizer": {
"details": {
"yul": true,
"yulDetails": {
"optimizerSteps": "a[a]["
}
}
}
}
}

View File

@ -0,0 +1 @@
{"errors":[{"component":"general","formattedMessage":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets","message":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets","severity":"error","type":"JSONError"}]}

View File

@ -21,11 +21,15 @@
#include <string>
#include <boost/test/unit_test.hpp>
#include <libsolidity/interface/OptimiserSettings.h>
#include <libsolidity/interface/StandardCompiler.h>
#include <libsolidity/interface/Version.h>
#include <libsolutil/JSON.h>
#include <libsolutil/CommonData.h>
#include <test/Metadata.h>
#include <set>
using namespace std;
using namespace solidity::evmasm;
@ -1058,8 +1062,12 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_details_different)
BOOST_CHECK(optimizer["details"]["peephole"].asBool() == true);
BOOST_CHECK(optimizer["details"]["yul"].asBool() == true);
BOOST_CHECK(optimizer["details"]["yulDetails"].isObject());
BOOST_CHECK(optimizer["details"]["yulDetails"].getMemberNames() == vector<string>{"stackAllocation"});
BOOST_CHECK(
util::convertContainer<set<string>>(optimizer["details"]["yulDetails"].getMemberNames()) ==
(set<string>{"stackAllocation", "optimizerSteps"})
);
BOOST_CHECK(optimizer["details"]["yulDetails"]["stackAllocation"].asBool() == true);
BOOST_CHECK(optimizer["details"]["yulDetails"]["optimizerSteps"].asString() == OptimiserSettings::DefaultYulOptimiserSteps);
BOOST_CHECK_EQUAL(optimizer["details"].getMemberNames().size(), 8);
BOOST_CHECK(optimizer["runs"].asUInt() == 600);
}