mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Change semantics tests to use the proper via IR pipeline and make optimizer requirements explicit.
This commit is contained in:
parent
8fafdeacac
commit
153b0bf4ba
@ -81,6 +81,16 @@ SemanticTest::SemanticTest(
|
|||||||
m_enforceCompileToEwasm = false;
|
m_enforceCompileToEwasm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string requiresYulOptimizer = m_reader.stringSetting("requiresYulOptimizer", "false");
|
||||||
|
if (requiresYulOptimizer == "false")
|
||||||
|
m_requiresYulOptimizer = RequiresYulOptimizer::False;
|
||||||
|
else if (requiresYulOptimizer == "minimalStack")
|
||||||
|
m_requiresYulOptimizer = RequiresYulOptimizer::MinimalStack;
|
||||||
|
else if (requiresYulOptimizer == "full")
|
||||||
|
m_requiresYulOptimizer = RequiresYulOptimizer::Full;
|
||||||
|
else
|
||||||
|
BOOST_THROW_EXCEPTION(runtime_error("Invalid requiresYulOptimizer value: " + requiresYulOptimizer + "."));
|
||||||
|
|
||||||
string compileToEwasm = m_reader.stringSetting("compileToEwasm", "false");
|
string compileToEwasm = m_reader.stringSetting("compileToEwasm", "false");
|
||||||
if (compileToEwasm == "also")
|
if (compileToEwasm == "also")
|
||||||
m_testCaseWantsEwasmRun = true;
|
m_testCaseWantsEwasmRun = true;
|
||||||
@ -307,7 +317,52 @@ TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePref
|
|||||||
result = runTest(_stream, _linePrefix, _formatted, false, false);
|
result = runTest(_stream, _linePrefix, _formatted, false, false);
|
||||||
|
|
||||||
if ((m_testCaseWantsYulRun || m_enforceViaYul) && result == TestResult::Success)
|
if ((m_testCaseWantsYulRun || m_enforceViaYul) && result == TestResult::Success)
|
||||||
result = runTest(_stream, _linePrefix, _formatted, true, false);
|
{
|
||||||
|
if (solidity::test::CommonOptions::get().optimize)
|
||||||
|
result = runTest(_stream, _linePrefix, _formatted, true, false);
|
||||||
|
else
|
||||||
|
for (auto requiresYulOptimizer: {RequiresYulOptimizer::False, RequiresYulOptimizer::MinimalStack, RequiresYulOptimizer::Full})
|
||||||
|
{
|
||||||
|
ScopedSaveAndRestore optimizerSettings(m_optimiserSettings, OptimiserSettings::minimal());
|
||||||
|
if (requiresYulOptimizer == RequiresYulOptimizer::MinimalStack)
|
||||||
|
{
|
||||||
|
m_optimiserSettings.runYulOptimiser = true;
|
||||||
|
m_optimiserSettings.yulOptimiserSteps = "uljmul jmul";
|
||||||
|
}
|
||||||
|
else if (requiresYulOptimizer == RequiresYulOptimizer::Full)
|
||||||
|
m_optimiserSettings = OptimiserSettings::full();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = runTest(_stream, _linePrefix, _formatted, true, false);
|
||||||
|
if (m_requiresYulOptimizer != requiresYulOptimizer)
|
||||||
|
{
|
||||||
|
static constexpr auto settingToString = [](RequiresYulOptimizer _setting) {
|
||||||
|
switch (_setting)
|
||||||
|
{
|
||||||
|
case RequiresYulOptimizer::False:
|
||||||
|
return "false";
|
||||||
|
case RequiresYulOptimizer::MinimalStack:
|
||||||
|
return "minimalStack";
|
||||||
|
case RequiresYulOptimizer::Full:
|
||||||
|
return "full";
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
};
|
||||||
|
m_canUpdateYulOptimizerRequirement = requiresYulOptimizer;
|
||||||
|
AnsiColorized(_stream, _formatted, {BOLD, YELLOW}) << _linePrefix << endl
|
||||||
|
<< _linePrefix << "requiresYulOptimizer is set to " << settingToString(m_requiresYulOptimizer)
|
||||||
|
<< " but should be " << settingToString(requiresYulOptimizer) << endl;
|
||||||
|
return TestResult::Failure;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (yul::StackTooDeepError const&)
|
||||||
|
{
|
||||||
|
if (requiresYulOptimizer == RequiresYulOptimizer::Full)
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((m_testCaseWantsEwasmRun || m_enforceCompileToEwasm) && result == TestResult::Success)
|
if ((m_testCaseWantsEwasmRun || m_enforceCompileToEwasm) && result == TestResult::Success)
|
||||||
{
|
{
|
||||||
@ -330,7 +385,8 @@ TestCase::TestResult SemanticTest::runTest(
|
|||||||
string const& _linePrefix,
|
string const& _linePrefix,
|
||||||
bool _formatted,
|
bool _formatted,
|
||||||
bool _isYulRun,
|
bool _isYulRun,
|
||||||
bool _isEwasmRun)
|
bool _isEwasmRun
|
||||||
|
)
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
m_gasCostFailure = false;
|
m_gasCostFailure = false;
|
||||||
@ -666,11 +722,26 @@ void SemanticTest::printUpdatedSettings(ostream& _stream, string const& _linePre
|
|||||||
}
|
}
|
||||||
else if (m_canEnableYulRun)
|
else if (m_canEnableYulRun)
|
||||||
_stream << _linePrefix << "// compileViaYul: also\n";
|
_stream << _linePrefix << "// compileViaYul: also\n";
|
||||||
|
if (m_canUpdateYulOptimizerRequirement)
|
||||||
|
{
|
||||||
|
switch (*m_canUpdateYulOptimizerRequirement)
|
||||||
|
{
|
||||||
|
case RequiresYulOptimizer::False:
|
||||||
|
break;
|
||||||
|
case RequiresYulOptimizer::MinimalStack:
|
||||||
|
_stream << _linePrefix << "// requiresYulOptimizer: minimalStack\n";
|
||||||
|
break;
|
||||||
|
case RequiresYulOptimizer::Full:
|
||||||
|
_stream << _linePrefix << "// requiresYulOptimizer: full\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto const& [settingName, settingValue]: settings)
|
for (auto const& [settingName, settingValue]: settings)
|
||||||
if (
|
if (
|
||||||
!(settingName == "compileToEwasm" && m_canEnableEwasmRun) &&
|
!(settingName == "compileToEwasm" && m_canEnableEwasmRun) &&
|
||||||
!(settingName == "compileViaYul" && (m_canEnableYulRun || m_canEnableEwasmRun))
|
!(settingName == "compileViaYul" && (m_canEnableYulRun || m_canEnableEwasmRun)) &&
|
||||||
|
!(settingName == "requiresYulOptimizer" && m_canUpdateYulOptimizerRequirement)
|
||||||
)
|
)
|
||||||
_stream << _linePrefix << "// " << settingName << ": " << settingValue<< endl;
|
_stream << _linePrefix << "// " << settingName << ": " << settingValue<< endl;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,17 @@ public:
|
|||||||
bool deploy(std::string const& _contractName, u256 const& _value, bytes const& _arguments, std::map<std::string, solidity::test::Address> const& _libraries = {});
|
bool deploy(std::string const& _contractName, u256 const& _value, bytes const& _arguments, std::map<std::string, solidity::test::Address> const& _libraries = {});
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TestResult runTest(std::ostream& _stream, std::string const& _linePrefix, bool _formatted, bool _isYulRun, bool _isEwasmRun);
|
enum class RequiresYulOptimizer
|
||||||
|
{
|
||||||
|
False, MinimalStack, Full
|
||||||
|
};
|
||||||
|
TestResult runTest(
|
||||||
|
std::ostream& _stream,
|
||||||
|
std::string const& _linePrefix,
|
||||||
|
bool _formatted,
|
||||||
|
bool _isYulRun,
|
||||||
|
bool _isEwasmRun
|
||||||
|
);
|
||||||
bool checkGasCostExpectation(TestFunctionCall& io_test, bool _compileViaYul) const;
|
bool checkGasCostExpectation(TestFunctionCall& io_test, bool _compileViaYul) const;
|
||||||
std::map<std::string, Builtin> makeBuiltins();
|
std::map<std::string, Builtin> makeBuiltins();
|
||||||
std::vector<SideEffectHook> makeSideEffectHooks() const;
|
std::vector<SideEffectHook> makeSideEffectHooks() const;
|
||||||
@ -108,6 +118,8 @@ private:
|
|||||||
bool m_canEnableEwasmRun = false;
|
bool m_canEnableEwasmRun = false;
|
||||||
bool m_gasCostFailure = false;
|
bool m_gasCostFailure = false;
|
||||||
bool m_enforceGasCost = false;
|
bool m_enforceGasCost = false;
|
||||||
|
RequiresYulOptimizer m_requiresYulOptimizer = RequiresYulOptimizer::False;
|
||||||
|
std::optional<RequiresYulOptimizer> m_canUpdateYulOptimizerRequirement;
|
||||||
u256 m_enforceGasCostMinValue;
|
u256 m_enforceGasCostMinValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <boost/test/framework.hpp>
|
#include <boost/test/framework.hpp>
|
||||||
#include <test/libsolidity/SolidityExecutionFramework.h>
|
#include <test/libsolidity/SolidityExecutionFramework.h>
|
||||||
|
#include <libyul/Exceptions.h>
|
||||||
#include <liblangutil/Exceptions.h>
|
#include <liblangutil/Exceptions.h>
|
||||||
#include <liblangutil/SourceReferenceFormatter.h>
|
#include <liblangutil/SourceReferenceFormatter.h>
|
||||||
|
|
||||||
@ -49,14 +50,15 @@ bytes SolidityExecutionFramework::multiSourceCompileContract(
|
|||||||
|
|
||||||
m_compiler.reset();
|
m_compiler.reset();
|
||||||
m_compiler.enableEwasmGeneration(m_compileToEwasm);
|
m_compiler.enableEwasmGeneration(m_compileToEwasm);
|
||||||
m_compiler.setSources(sourcesWithPreamble);
|
m_compiler.enableEvmBytecodeGeneration(!m_compileToEwasm);
|
||||||
|
m_compiler.setViaIR(m_compileViaYul || m_compileToEwasm);
|
||||||
|
m_compiler.setSources(move(sourcesWithPreamble));
|
||||||
m_compiler.setLibraries(_libraryAddresses);
|
m_compiler.setLibraries(_libraryAddresses);
|
||||||
m_compiler.setRevertStringBehaviour(m_revertStrings);
|
m_compiler.setRevertStringBehaviour(m_revertStrings);
|
||||||
m_compiler.setEVMVersion(m_evmVersion);
|
m_compiler.setEVMVersion(m_evmVersion);
|
||||||
m_compiler.setOptimiserSettings(m_optimiserSettings);
|
m_compiler.setOptimiserSettings(m_optimiserSettings);
|
||||||
m_compiler.enableEvmBytecodeGeneration(!m_compileViaYul);
|
|
||||||
m_compiler.enableIRGeneration(m_compileViaYul);
|
|
||||||
m_compiler.setRevertStringBehaviour(m_revertStrings);
|
m_compiler.setRevertStringBehaviour(m_revertStrings);
|
||||||
|
|
||||||
if (!m_compiler.compile())
|
if (!m_compiler.compile())
|
||||||
{
|
{
|
||||||
// The testing framework expects an exception for
|
// The testing framework expects an exception for
|
||||||
@ -69,50 +71,9 @@ bytes SolidityExecutionFramework::multiSourceCompileContract(
|
|||||||
.printErrorInformation(m_compiler.errors());
|
.printErrorInformation(m_compiler.errors());
|
||||||
BOOST_ERROR("Compiling contract failed");
|
BOOST_ERROR("Compiling contract failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
string contractName(_contractName.empty() ? m_compiler.lastContractName(_mainSourceName) : _contractName);
|
string contractName(_contractName.empty() ? m_compiler.lastContractName(_mainSourceName) : _contractName);
|
||||||
evmasm::LinkerObject obj;
|
evmasm::LinkerObject obj = m_compileToEwasm ? m_compiler.ewasmObject(contractName) : m_compiler.object(contractName);
|
||||||
if (m_compileViaYul)
|
|
||||||
{
|
|
||||||
if (m_compileToEwasm)
|
|
||||||
obj = m_compiler.ewasmObject(contractName);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Try compiling twice: If the first run fails due to stack errors, forcefully enable
|
|
||||||
// the optimizer.
|
|
||||||
for (bool forceEnableOptimizer: {false, true})
|
|
||||||
{
|
|
||||||
OptimiserSettings optimiserSettings = m_optimiserSettings;
|
|
||||||
if (!forceEnableOptimizer && !optimiserSettings.runYulOptimiser)
|
|
||||||
{
|
|
||||||
// Enable some optimizations on the first run
|
|
||||||
optimiserSettings.runYulOptimiser = true;
|
|
||||||
optimiserSettings.yulOptimiserSteps = "uljmul jmul";
|
|
||||||
}
|
|
||||||
else if (forceEnableOptimizer)
|
|
||||||
optimiserSettings = OptimiserSettings::full();
|
|
||||||
|
|
||||||
yul::AssemblyStack
|
|
||||||
asmStack(m_evmVersion, yul::AssemblyStack::Language::StrictAssembly, optimiserSettings);
|
|
||||||
bool analysisSuccessful = asmStack.parseAndAnalyze("", m_compiler.yulIROptimized(contractName));
|
|
||||||
solAssert(analysisSuccessful, "Code that passed analysis in CompilerStack can't have errors");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
asmStack.optimize();
|
|
||||||
obj = move(*asmStack.assemble(yul::AssemblyStack::Machine::EVM).bytecode);
|
|
||||||
obj.link(_libraryAddresses);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
if (forceEnableOptimizer || optimiserSettings == OptimiserSettings::full())
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
obj = m_compiler.object(contractName);
|
|
||||||
BOOST_REQUIRE(obj.linkReferences.empty());
|
BOOST_REQUIRE(obj.linkReferences.empty());
|
||||||
if (m_showMetadata)
|
if (m_showMetadata)
|
||||||
cout << "metadata: " << m_compiler.metadata(contractName) << endl;
|
cout << "metadata: " << m_compiler.metadata(contractName) << endl;
|
||||||
|
Loading…
Reference in New Issue
Block a user