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;
|
||||
}
|
||||
|
||||
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");
|
||||
if (compileToEwasm == "also")
|
||||
m_testCaseWantsEwasmRun = true;
|
||||
@ -307,7 +317,52 @@ TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePref
|
||||
result = runTest(_stream, _linePrefix, _formatted, false, false);
|
||||
|
||||
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)
|
||||
{
|
||||
@ -330,7 +385,8 @@ TestCase::TestResult SemanticTest::runTest(
|
||||
string const& _linePrefix,
|
||||
bool _formatted,
|
||||
bool _isYulRun,
|
||||
bool _isEwasmRun)
|
||||
bool _isEwasmRun
|
||||
)
|
||||
{
|
||||
bool success = true;
|
||||
m_gasCostFailure = false;
|
||||
@ -666,11 +722,26 @@ void SemanticTest::printUpdatedSettings(ostream& _stream, string const& _linePre
|
||||
}
|
||||
else if (m_canEnableYulRun)
|
||||
_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)
|
||||
if (
|
||||
!(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;
|
||||
}
|
||||
|
@ -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 = {});
|
||||
|
||||
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;
|
||||
std::map<std::string, Builtin> makeBuiltins();
|
||||
std::vector<SideEffectHook> makeSideEffectHooks() const;
|
||||
@ -108,6 +118,8 @@ private:
|
||||
bool m_canEnableEwasmRun = false;
|
||||
bool m_gasCostFailure = false;
|
||||
bool m_enforceGasCost = false;
|
||||
RequiresYulOptimizer m_requiresYulOptimizer = RequiresYulOptimizer::False;
|
||||
std::optional<RequiresYulOptimizer> m_canUpdateYulOptimizerRequirement;
|
||||
u256 m_enforceGasCostMinValue;
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <iostream>
|
||||
#include <boost/test/framework.hpp>
|
||||
#include <test/libsolidity/SolidityExecutionFramework.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
#include <liblangutil/Exceptions.h>
|
||||
#include <liblangutil/SourceReferenceFormatter.h>
|
||||
|
||||
@ -49,14 +50,15 @@ bytes SolidityExecutionFramework::multiSourceCompileContract(
|
||||
|
||||
m_compiler.reset();
|
||||
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.setRevertStringBehaviour(m_revertStrings);
|
||||
m_compiler.setEVMVersion(m_evmVersion);
|
||||
m_compiler.setOptimiserSettings(m_optimiserSettings);
|
||||
m_compiler.enableEvmBytecodeGeneration(!m_compileViaYul);
|
||||
m_compiler.enableIRGeneration(m_compileViaYul);
|
||||
m_compiler.setRevertStringBehaviour(m_revertStrings);
|
||||
|
||||
if (!m_compiler.compile())
|
||||
{
|
||||
// The testing framework expects an exception for
|
||||
@ -69,50 +71,9 @@ bytes SolidityExecutionFramework::multiSourceCompileContract(
|
||||
.printErrorInformation(m_compiler.errors());
|
||||
BOOST_ERROR("Compiling contract failed");
|
||||
}
|
||||
|
||||
string contractName(_contractName.empty() ? m_compiler.lastContractName(_mainSourceName) : _contractName);
|
||||
evmasm::LinkerObject obj;
|
||||
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);
|
||||
evmasm::LinkerObject obj = m_compileToEwasm ? m_compiler.ewasmObject(contractName) : m_compiler.object(contractName);
|
||||
BOOST_REQUIRE(obj.linkReferences.empty());
|
||||
if (m_showMetadata)
|
||||
cout << "metadata: " << m_compiler.metadata(contractName) << endl;
|
||||
|
Loading…
Reference in New Issue
Block a user