This commit is contained in:
Daniel Kirchner 2022-12-05 16:17:55 +01:00
parent 3ff457c312
commit ffb3a2bdd9
30 changed files with 118 additions and 66 deletions

View File

@ -49,7 +49,7 @@ using AssemblyPointer = std::shared_ptr<Assembly>;
class Assembly class Assembly
{ {
public: public:
Assembly(bool _creation, std::string _name): m_creation(_creation), m_name(std::move(_name)) { } Assembly(langutil::EVMVersion _evmVersion, std::optional<uint8_t> _eofVersion, bool _creation, std::string _name): m_creation(_creation), m_name(std::move(_name)), m_evmVersion(_evmVersion), m_eofVersion(_eofVersion) { }
AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); } AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); }
AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); } AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); }
@ -93,11 +93,11 @@ public:
} }
unsigned maxDup() const unsigned maxDup() const
{ {
return 16; return m_eofVersion.has_value() ? 256 : 16;
} }
unsigned maxSwap() const unsigned maxSwap() const
{ {
return 16; return m_eofVersion.has_value() ? 256 : 16;
} }
AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; } AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; }
@ -234,8 +234,13 @@ protected:
langutil::SourceLocation m_currentSourceLocation; langutil::SourceLocation m_currentSourceLocation;
langutil::EVMVersion const m_evmVersion;
std::optional<uint8_t> const m_eofVersion;
public: public:
size_t m_currentModifierDepth = 0; size_t m_currentModifierDepth = 0;
langutil::EVMVersion evmVersion() const { return m_evmVersion; }
std::optional<uint8_t> eofVersion() const { return m_eofVersion; }
}; };
inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a) inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a)

View File

@ -37,10 +37,10 @@ namespace solidity::frontend
class Compiler class Compiler
{ {
public: public:
Compiler(langutil::EVMVersion _evmVersion, RevertStrings _revertStrings, OptimiserSettings _optimiserSettings): Compiler(langutil::EVMVersion _evmVersion, std::optional<uint8_t> _eofVersion, RevertStrings _revertStrings, OptimiserSettings _optimiserSettings):
m_optimiserSettings(std::move(_optimiserSettings)), m_optimiserSettings(std::move(_optimiserSettings)),
m_runtimeContext(_evmVersion, _revertStrings), m_runtimeContext(_evmVersion, _eofVersion, _revertStrings),
m_context(_evmVersion, _revertStrings, &m_runtimeContext) m_context(_evmVersion, _eofVersion, _revertStrings, &m_runtimeContext)
{ } { }
/// Compiles a contract. /// Compiles a contract.

View File

@ -549,7 +549,9 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
_optimiserSettings.yulOptimiserSteps, _optimiserSettings.yulOptimiserSteps,
_optimiserSettings.yulOptimiserCleanupSteps, _optimiserSettings.yulOptimiserCleanupSteps,
isCreation? nullopt : make_optional(_optimiserSettings.expectedExecutionsPerDeployment), isCreation? nullopt : make_optional(_optimiserSettings.expectedExecutionsPerDeployment),
_externalIdentifiers _externalIdentifiers,
m_asm->maxSwap(),
m_asm->maxDup()
); );
#ifdef SOL_OUTPUT_ASM #ifdef SOL_OUTPUT_ASM

View File

@ -62,10 +62,11 @@ class CompilerContext
public: public:
explicit CompilerContext( explicit CompilerContext(
langutil::EVMVersion _evmVersion, langutil::EVMVersion _evmVersion,
std::optional<uint8_t> _eofVersion,
RevertStrings _revertStrings, RevertStrings _revertStrings,
CompilerContext* _runtimeContext = nullptr CompilerContext* _runtimeContext = nullptr
): ):
m_asm(std::make_shared<evmasm::Assembly>(_runtimeContext != nullptr, std::string{})), m_asm(std::make_shared<evmasm::Assembly>(_evmVersion, _eofVersion, _runtimeContext != nullptr, std::string{})),
m_evmVersion(_evmVersion), m_evmVersion(_evmVersion),
m_revertStrings(_revertStrings), m_revertStrings(_revertStrings),
m_reservedMemory{0}, m_reservedMemory{0},

View File

@ -1333,7 +1333,7 @@ void CompilerStack::compileContract(
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
shared_ptr<Compiler> compiler = make_shared<Compiler>(m_evmVersion, m_revertStrings, m_optimiserSettings); shared_ptr<Compiler> compiler = make_shared<Compiler>(m_evmVersion, m_eofVersion, m_revertStrings, m_optimiserSettings);
compiledContract.compiler = compiler; compiledContract.compiler = compiler;
solAssert(!m_viaIR, ""); solAssert(!m_viaIR, "");

View File

@ -34,7 +34,9 @@ using namespace solidity::util;
CompilabilityChecker::CompilabilityChecker( CompilabilityChecker::CompilabilityChecker(
Dialect const& _dialect, Dialect const& _dialect,
Object const& _object, Object const& _object,
bool _optimizeStackAllocation bool _optimizeStackAllocation,
unsigned _maxDup,
unsigned _maxSwap
) )
{ {
if (auto const* evmDialect = dynamic_cast<EVMDialect const*>(&_dialect)) if (auto const* evmDialect = dynamic_cast<EVMDialect const*>(&_dialect))
@ -50,7 +52,7 @@ CompilabilityChecker::CompilabilityChecker(
builtinContext.subIDs[_object.name] = 1; builtinContext.subIDs[_object.name] = 1;
for (auto const& subNode: _object.subObjects) for (auto const& subNode: _object.subObjects)
builtinContext.subIDs[subNode->name] = 1; builtinContext.subIDs[subNode->name] = 1;
NoOutputAssembly assembly; NoOutputAssembly assembly(_maxSwap, _maxDup);
CodeTransform transform( CodeTransform transform(
assembly, assembly,
analysisInfo, analysisInfo,

View File

@ -44,7 +44,7 @@ namespace solidity::yul
*/ */
struct CompilabilityChecker struct CompilabilityChecker
{ {
CompilabilityChecker(Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation); CompilabilityChecker(Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation, unsigned _maxSwap, unsigned _maxDup);
std::map<YulString, std::set<YulString>> unreachableVariables; std::map<YulString, std::set<YulString>> unreachableVariables;
std::map<YulString, int> stackDeficit; std::map<YulString, int> stackDeficit;
}; };

View File

@ -179,6 +179,11 @@ void YulStack::optimize(Object& _object, bool _isCreation)
} }
Dialect const& dialect = languageToDialect(m_language, m_evmVersion); Dialect const& dialect = languageToDialect(m_language, m_evmVersion);
// TODO
unsigned maxSwap = m_eofVersion.has_value() ? 256 : 16;
unsigned maxDup = m_eofVersion.has_value() ? 256 : 16;
unique_ptr<GasMeter> meter; unique_ptr<GasMeter> meter;
if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&dialect)) if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&dialect))
meter = make_unique<GasMeter>(*evmDialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment); meter = make_unique<GasMeter>(*evmDialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment);
@ -190,7 +195,9 @@ void YulStack::optimize(Object& _object, bool _isCreation)
m_optimiserSettings.yulOptimiserSteps, m_optimiserSettings.yulOptimiserSteps,
m_optimiserSettings.yulOptimiserCleanupSteps, m_optimiserSettings.yulOptimiserCleanupSteps,
_isCreation ? nullopt : make_optional(m_optimiserSettings.expectedExecutionsPerDeployment), _isCreation ? nullopt : make_optional(m_optimiserSettings.expectedExecutionsPerDeployment),
{} {},
maxSwap,
maxDup
); );
} }
@ -264,7 +271,7 @@ YulStack::assembleEVMWithDeployed(optional<string_view> _deployName) const
yulAssert(m_parserResult->code, ""); yulAssert(m_parserResult->code, "");
yulAssert(m_parserResult->analysisInfo, ""); yulAssert(m_parserResult->analysisInfo, "");
evmasm::Assembly assembly(true, {}); evmasm::Assembly assembly(m_evmVersion, m_eofVersion, true, {});
EthAssemblyAdapter adapter(assembly); EthAssemblyAdapter adapter(assembly);
compileEVM(adapter, m_optimiserSettings.optimizeStackAllocation); compileEVM(adapter, m_optimiserSettings.optimizeStackAllocation);

View File

@ -146,7 +146,7 @@ void EthAssemblyAdapter::appendAssemblySize()
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, string _name) pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, string _name)
{ {
shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>(_creation, std::move(_name))}; shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>(m_assembly.evmVersion(), m_assembly.eofVersion(), _creation, std::move(_name))};
auto sub = m_assembly.newSub(assembly); auto sub = m_assembly.newSub(assembly);
return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())}; return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())};
} }

View File

@ -50,11 +50,11 @@ void NoOutputAssembly::appendDup(unsigned)
} }
unsigned NoOutputAssembly::maxDup() const unsigned NoOutputAssembly::maxDup() const
{ {
return 16; return m_maxDup;
} }
unsigned NoOutputAssembly::maxSwap() const unsigned NoOutputAssembly::maxSwap() const
{ {
return 16; return m_maxSwap;
} }
void NoOutputAssembly::appendConstant(u256 const&) void NoOutputAssembly::appendConstant(u256 const&)
{ {

View File

@ -45,7 +45,7 @@ namespace solidity::yul
class NoOutputAssembly: public AbstractAssembly class NoOutputAssembly: public AbstractAssembly
{ {
public: public:
explicit NoOutputAssembly() { } explicit NoOutputAssembly(unsigned _maxSwap, unsigned _maxDup): m_maxSwap(_maxSwap), m_maxDup(_maxDup) { }
~NoOutputAssembly() override = default; ~NoOutputAssembly() override = default;
void setSourceLocation(langutil::SourceLocation const&) override {} void setSourceLocation(langutil::SourceLocation const&) override {}
@ -83,6 +83,8 @@ public:
private: private:
int m_stackHeight = 0; int m_stackHeight = 0;
unsigned m_maxSwap = 16;
unsigned m_maxDup = 16;
}; };

View File

@ -50,7 +50,7 @@ vector<StackTooDeepError> OptimizedEVMCodeTransform::run(
) )
{ {
std::unique_ptr<CFG> dfg = ControlFlowGraphBuilder::build(_analysisInfo, _dialect, _block); std::unique_ptr<CFG> dfg = ControlFlowGraphBuilder::build(_analysisInfo, _dialect, _block);
StackLayout stackLayout = StackLayoutGenerator::run(*dfg); StackLayout stackLayout = StackLayoutGenerator::run(*dfg, _assembly.maxSwap(), _assembly.maxDup());
OptimizedEVMCodeTransform optimizedCodeTransform( OptimizedEVMCodeTransform optimizedCodeTransform(
_assembly, _assembly,
_builtinContext, _builtinContext,

View File

@ -48,28 +48,28 @@ using namespace solidity;
using namespace solidity::yul; using namespace solidity::yul;
using namespace std; using namespace std;
StackLayout StackLayoutGenerator::run(CFG const& _cfg) StackLayout StackLayoutGenerator::run(CFG const& _cfg, unsigned _maxSwap, unsigned _maxDup)
{ {
StackLayout stackLayout; StackLayout stackLayout;
StackLayoutGenerator{stackLayout}.processEntryPoint(*_cfg.entry); StackLayoutGenerator{stackLayout, _maxSwap, _maxDup}.processEntryPoint(*_cfg.entry);
for (auto& functionInfo: _cfg.functionInfo | ranges::views::values) for (auto& functionInfo: _cfg.functionInfo | ranges::views::values)
StackLayoutGenerator{stackLayout}.processEntryPoint(*functionInfo.entry, &functionInfo); StackLayoutGenerator{stackLayout, _maxSwap, _maxDup}.processEntryPoint(*functionInfo.entry, &functionInfo);
return stackLayout; return stackLayout;
} }
map<YulString, vector<StackLayoutGenerator::StackTooDeep>> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg) map<YulString, vector<StackLayoutGenerator::StackTooDeep>> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, unsigned _maxSwap, unsigned _maxDup)
{ {
map<YulString, vector<StackLayoutGenerator::StackTooDeep>> stackTooDeepErrors; map<YulString, vector<StackLayoutGenerator::StackTooDeep>> stackTooDeepErrors;
stackTooDeepErrors[YulString{}] = reportStackTooDeep(_cfg, YulString{}); stackTooDeepErrors[YulString{}] = reportStackTooDeep(_cfg, YulString{}, _maxSwap, _maxDup);
for (auto const& function: _cfg.functions) for (auto const& function: _cfg.functions)
if (auto errors = reportStackTooDeep(_cfg, function->name); !errors.empty()) if (auto errors = reportStackTooDeep(_cfg, function->name, _maxSwap, _maxDup); !errors.empty())
stackTooDeepErrors[function->name] = std::move(errors); stackTooDeepErrors[function->name] = std::move(errors);
return stackTooDeepErrors; return stackTooDeepErrors;
} }
vector<StackLayoutGenerator::StackTooDeep> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulString _functionName) vector<StackLayoutGenerator::StackTooDeep> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulString _functionName, unsigned _maxSwap, unsigned _maxDup)
{ {
StackLayout stackLayout; StackLayout stackLayout;
CFG::FunctionInfo const* functionInfo = nullptr; CFG::FunctionInfo const* functionInfo = nullptr;
@ -83,13 +83,13 @@ vector<StackLayoutGenerator::StackTooDeep> StackLayoutGenerator::reportStackTooD
yulAssert(functionInfo, "Function not found."); yulAssert(functionInfo, "Function not found.");
} }
StackLayoutGenerator generator{stackLayout}; StackLayoutGenerator generator{stackLayout, _maxSwap, _maxDup};
CFG::BasicBlock const* entry = functionInfo ? functionInfo->entry : _cfg.entry; CFG::BasicBlock const* entry = functionInfo ? functionInfo->entry : _cfg.entry;
generator.processEntryPoint(*entry); generator.processEntryPoint(*entry);
return generator.reportStackTooDeep(*entry); return generator.reportStackTooDeep(*entry);
} }
StackLayoutGenerator::StackLayoutGenerator(StackLayout& _layout): m_layout(_layout) StackLayoutGenerator::StackLayoutGenerator(StackLayout& _layout, unsigned _maxSwap, unsigned _maxDup): m_layout(_layout), m_maxSwap(_maxSwap), m_maxDup(_maxDup)
{ {
} }

View File

@ -55,18 +55,18 @@ public:
std::vector<YulString> variableChoices; std::vector<YulString> variableChoices;
}; };
static StackLayout run(CFG const& _cfg); static StackLayout run(CFG const& _cfg, unsigned _maxSwap, unsigned _maxDup);
/// @returns a map from function names to the stack too deep errors occurring in that function. /// @returns a map from function names to the stack too deep errors occurring in that function.
/// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul.
/// The empty string is mapped to the stack too deep errors of the main entry point. /// The empty string is mapped to the stack too deep errors of the main entry point.
static std::map<YulString, std::vector<StackTooDeep>> reportStackTooDeep(CFG const& _cfg); static std::map<YulString, std::vector<StackTooDeep>> reportStackTooDeep(CFG const& _cfg, unsigned _maxSwap, unsigned _maxDup);
/// @returns all stack too deep errors in the function named @a _functionName. /// @returns all stack too deep errors in the function named @a _functionName.
/// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul.
/// If @a _functionName is empty, the stack too deep errors of the main entry point are reported instead. /// If @a _functionName is empty, the stack too deep errors of the main entry point are reported instead.
static std::vector<StackTooDeep> reportStackTooDeep(CFG const& _cfg, YulString _functionName); static std::vector<StackTooDeep> reportStackTooDeep(CFG const& _cfg, YulString _functionName, unsigned _maxSwap, unsigned _maxDup);
private: private:
StackLayoutGenerator(StackLayout& _context); StackLayoutGenerator(StackLayout& _context, unsigned _maxSwap, unsigned _maxDup);
/// @returns the optimal entry stack layout, s.t. @a _operation can be applied to it and /// @returns the optimal entry stack layout, s.t. @a _operation can be applied to it and
/// the result can be transformed to @a _exitStack with minimal stack shuffling. /// the result can be transformed to @a _exitStack with minimal stack shuffling.
@ -116,9 +116,10 @@ private:
StackLayout& m_layout; StackLayout& m_layout;
// TODO unsigned maxSwap() const { return m_maxSwap; }
unsigned maxSwap() const { return 16; } unsigned maxDup() const { return m_maxDup; }
unsigned maxDup() const { return 16; } unsigned const m_maxSwap = 16;
unsigned const m_maxDup = 16;
}; };
} }

View File

@ -39,6 +39,9 @@ struct OptimiserStepContext
std::set<YulString> const& reservedIdentifiers; std::set<YulString> const& reservedIdentifiers;
/// The value nullopt represents creation code /// The value nullopt represents creation code
std::optional<size_t> expectedExecutionsPerDeployment; std::optional<size_t> expectedExecutionsPerDeployment;
unsigned maxSwap = 16;
unsigned maxDup = 16;
}; };

View File

@ -240,7 +240,9 @@ bool StackCompressor::run(
Dialect const& _dialect, Dialect const& _dialect,
Object& _object, Object& _object,
bool _optimizeStackAllocation, bool _optimizeStackAllocation,
size_t _maxIterations size_t _maxIterations,
unsigned _maxSwap,
unsigned _maxDup
) )
{ {
yulAssert( yulAssert(
@ -262,14 +264,14 @@ bool StackCompressor::run(
eliminateVariablesOptimizedCodegen( eliminateVariablesOptimizedCodegen(
_dialect, _dialect,
*_object.code, *_object.code,
StackLayoutGenerator::reportStackTooDeep(*cfg), StackLayoutGenerator::reportStackTooDeep(*cfg, _maxSwap, _maxDup),
allowMSizeOptimzation allowMSizeOptimzation
); );
} }
else else
for (size_t iterations = 0; iterations < _maxIterations; iterations++) for (size_t iterations = 0; iterations < _maxIterations; iterations++)
{ {
map<YulString, int> stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation).stackDeficit; map<YulString, int> stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation, _maxSwap, _maxDup).stackDeficit;
if (stackSurplus.empty()) if (stackSurplus.empty())
return true; return true;
eliminateVariables( eliminateVariables(

View File

@ -50,7 +50,9 @@ public:
Dialect const& _dialect, Dialect const& _dialect,
Object& _object, Object& _object,
bool _optimizeStackAllocation, bool _optimizeStackAllocation,
size_t _maxIterations size_t _maxIterations,
unsigned _maxSwap,
unsigned _maxDup
); );
}; };

View File

@ -132,13 +132,15 @@ void StackLimitEvader::run(
{ {
yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, _object); yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, _object);
unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, *_object.code); unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, *_object.code);
run(_context, _object, StackLayoutGenerator::reportStackTooDeep(*cfg)); run(_context, _object, StackLayoutGenerator::reportStackTooDeep(*cfg, _context.maxSwap, _context.maxDup));
} }
else else
run(_context, _object, CompilabilityChecker{ run(_context, _object, CompilabilityChecker{
_context.dialect, _context.dialect,
_object, _object,
true true,
_context.maxSwap,
_context.maxDup
}.unreachableVariables); }.unreachableVariables);
} }

View File

@ -141,7 +141,9 @@ void OptimiserSuite::run(
string_view _optimisationSequence, string_view _optimisationSequence,
string_view _optimisationCleanupSequence, string_view _optimisationCleanupSequence,
optional<size_t> _expectedExecutionsPerDeployment, optional<size_t> _expectedExecutionsPerDeployment,
set<YulString> const& _externallyUsedIdentifiers set<YulString> const& _externallyUsedIdentifiers,
unsigned _maxSwap,
unsigned _maxDup
) )
{ {
EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&_dialect); EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&_dialect);
@ -161,7 +163,7 @@ void OptimiserSuite::run(
Block& ast = *_object.code; Block& ast = *_object.code;
NameDispenser dispenser{_dialect, ast, reservedIdentifiers}; NameDispenser dispenser{_dialect, ast, reservedIdentifiers};
OptimiserStepContext context{_dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment}; OptimiserStepContext context{_dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment, _maxSwap, _maxDup};
OptimiserSuite suite(context, Debug::None); OptimiserSuite suite(context, Debug::None);
@ -184,7 +186,9 @@ void OptimiserSuite::run(
_dialect, _dialect,
_object, _object,
_optimizeStackAllocation, _optimizeStackAllocation,
stackCompressorMaxIterations stackCompressorMaxIterations,
context.maxSwap,
context.maxDup
); );
// Run the user-supplied clean up sequence // Run the user-supplied clean up sequence
@ -204,7 +208,9 @@ void OptimiserSuite::run(
_dialect, _dialect,
_object, _object,
_optimizeStackAllocation, _optimizeStackAllocation,
stackCompressorMaxIterations stackCompressorMaxIterations,
context.maxSwap,
context.maxDup
); );
if (evmDialect->providesObjectAccess()) if (evmDialect->providesObjectAccess())
StackLimitEvader::run(suite.m_context, _object); StackLimitEvader::run(suite.m_context, _object);

View File

@ -70,7 +70,9 @@ public:
std::string_view _optimisationSequence, std::string_view _optimisationSequence,
std::string_view _optimisationCleanupSequence, std::string_view _optimisationCleanupSequence,
std::optional<size_t> _expectedExecutionsPerDeployment, std::optional<size_t> _expectedExecutionsPerDeployment,
std::set<YulString> const& _externallyUsedIdentifiers = {} std::set<YulString> const& _externallyUsedIdentifiers,
unsigned _maxSwap,
unsigned _maxDup
); );
/// Ensures that specified sequence of step abbreviations is well-formed and can be executed. /// Ensures that specified sequence of step abbreviations is well-formed and can be executed.

View File

@ -59,15 +59,16 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
{ "sub.asm", 1 }, { "sub.asm", 1 },
{ "verbatim.asm", 2 } { "verbatim.asm", 2 }
}; };
Assembly _assembly{false, {}}; // TODO: versions
Assembly _assembly{{}, {}, false, {}};
auto root_asm = make_shared<string>("root.asm"); auto root_asm = make_shared<string>("root.asm");
_assembly.setSourceLocation({1, 3, root_asm}); _assembly.setSourceLocation({1, 3, root_asm});
Assembly _subAsm{false, {}}; Assembly _subAsm{{}, {}, false, {}};
auto sub_asm = make_shared<string>("sub.asm"); auto sub_asm = make_shared<string>("sub.asm");
_subAsm.setSourceLocation({6, 8, sub_asm}); _subAsm.setSourceLocation({6, 8, sub_asm});
Assembly _verbatimAsm(true, ""); Assembly _verbatimAsm({}, {}, true, "");
auto verbatim_asm = make_shared<string>("verbatim.asm"); auto verbatim_asm = make_shared<string>("verbatim.asm");
_verbatimAsm.setSourceLocation({8, 18, verbatim_asm}); _verbatimAsm.setSourceLocation({8, 18, verbatim_asm});
@ -243,7 +244,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps)
{ *subName, 1 } { *subName, 1 }
}; };
auto subAsm = make_shared<Assembly>(false, string{}); auto subAsm = make_shared<Assembly>(langutil::EVMVersion{}, std::nullopt, false, string{});
for (char i = 0; i < numImmutables; ++i) for (char i = 0; i < numImmutables; ++i)
{ {
for (int r = 0; r < numActualRefs; ++r) for (int r = 0; r < numActualRefs; ++r)
@ -253,7 +254,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps)
} }
} }
Assembly assembly{true, {}}; Assembly assembly{{}, {}, true, {}};
for (char i = 1; i <= numImmutables; ++i) for (char i = 1; i <= numImmutables; ++i)
{ {
assembly.setSourceLocation({10*i, 10*i + 3+i, assemblyName}); assembly.setSourceLocation({10*i, 10*i + 3+i, assemblyName});
@ -302,11 +303,11 @@ BOOST_AUTO_TEST_CASE(immutable)
{ "root.asm", 0 }, { "root.asm", 0 },
{ "sub.asm", 1 } { "sub.asm", 1 }
}; };
Assembly _assembly{true, {}}; Assembly _assembly{{}, {}, true, {}};
auto root_asm = make_shared<string>("root.asm"); auto root_asm = make_shared<string>("root.asm");
_assembly.setSourceLocation({1, 3, root_asm}); _assembly.setSourceLocation({1, 3, root_asm});
Assembly _subAsm{false, {}}; Assembly _subAsm{{}, {}, false, {}};
auto sub_asm = make_shared<string>("sub.asm"); auto sub_asm = make_shared<string>("sub.asm");
_subAsm.setSourceLocation({6, 8, sub_asm}); _subAsm.setSourceLocation({6, 8, sub_asm});
_subAsm.appendImmutable("someImmutable"); _subAsm.appendImmutable("someImmutable");
@ -395,10 +396,10 @@ BOOST_AUTO_TEST_CASE(immutable)
BOOST_AUTO_TEST_CASE(subobject_encode_decode) BOOST_AUTO_TEST_CASE(subobject_encode_decode)
{ {
Assembly assembly{true, {}}; Assembly assembly{{}, {}, true, {}};
shared_ptr<Assembly> subAsmPtr = make_shared<Assembly>(false, string{}); shared_ptr<Assembly> subAsmPtr = make_shared<Assembly>(langutil::EVMVersion{}, std::nullopt, false, string{});
shared_ptr<Assembly> subSubAsmPtr = make_shared<Assembly>(false, string{}); shared_ptr<Assembly> subSubAsmPtr = make_shared<Assembly>(langutil::EVMVersion{}, std::nullopt, false, string{});
assembly.appendSubroutine(subAsmPtr); assembly.appendSubroutine(subAsmPtr);
subAsmPtr->appendSubroutine(subSubAsmPtr); subAsmPtr->appendSubroutine(subSubAsmPtr);

View File

@ -1250,8 +1250,8 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies)
// tag unifications (due to block deduplication) is also // tag unifications (due to block deduplication) is also
// visible at the super-assembly. // visible at the super-assembly.
Assembly main{false, {}}; Assembly main{{}, {}, false, {}};
AssemblyPointer sub = make_shared<Assembly>(true, string{}); AssemblyPointer sub = make_shared<Assembly>(langutil::EVMVersion(), nullopt, true, string{});
sub->append(u256(1)); sub->append(u256(1));
auto t1 = sub->newTag(); auto t1 = sub->newTag();

View File

@ -87,6 +87,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode)
{ {
Compiler compiler( Compiler compiler(
solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().evmVersion(),
solidity::test::CommonOptions::get().eofVersion(),
RevertStrings::Default, RevertStrings::Default,
solidity::test::CommonOptions::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal() solidity::test::CommonOptions::get().optimize ? OptimiserSettings::standard() : OptimiserSettings::minimal()
); );

View File

@ -144,6 +144,7 @@ bytes compileFirstExpression(
CompilerContext context( CompilerContext context(
solidity::test::CommonOptions::get().evmVersion(), solidity::test::CommonOptions::get().evmVersion(),
solidity::test::CommonOptions::get().eofVersion(),
RevertStrings::Default RevertStrings::Default
); );
context.resetVisitedNodes(contract); context.resetVisitedNodes(contract);

View File

@ -39,7 +39,8 @@ string check(string const& _input)
Object obj; Object obj;
std::tie(obj.code, obj.analysisInfo) = yul::test::parse(_input, false); std::tie(obj.code, obj.analysisInfo) = yul::test::parse(_input, false);
BOOST_REQUIRE(obj.code); BOOST_REQUIRE(obj.code);
auto functions = CompilabilityChecker(EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()), obj, true).stackDeficit; // TODO: maxSwap, maxDup
auto functions = CompilabilityChecker(EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()), obj, true, 16u, 16u).stackDeficit;
string out; string out;
for (auto const& function: functions) for (auto const& function: functions)
out += function.first.str() + ": " + to_string(function.second) + " "; out += function.first.str() + ": " + to_string(function.second) + " ";

View File

@ -66,7 +66,7 @@ TestCase::TestResult EVMCodeTransformTest::run(ostream& _stream, string const& _
return TestResult::FatalError; return TestResult::FatalError;
} }
evmasm::Assembly assembly{false, {}}; evmasm::Assembly assembly{{}, {}, false, {}};
EthAssemblyAdapter adapter(assembly); EthAssemblyAdapter adapter(assembly);
EVMObjectCompiler::compile( EVMObjectCompiler::compile(
*stack.parserResult(), *stack.parserResult(),

View File

@ -226,7 +226,8 @@ TestCase::TestResult StackLayoutGeneratorTest::run(ostream& _stream, string cons
std::ostringstream output; std::ostringstream output;
std::unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, *object->code); std::unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, *object->code);
StackLayout stackLayout = StackLayoutGenerator::run(*cfg); // TODO maxSwap, maxDup
StackLayout stackLayout = StackLayoutGenerator::run(*cfg, 16u, 16u);
output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n";
StackLayoutPrinter printer{output, stackLayout}; StackLayoutPrinter printer{output, stackLayout};

View File

@ -323,7 +323,8 @@ YulOptimizerTestCommon::YulOptimizerTestCommon(
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
FunctionGrouper::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_ast);
size_t maxIterations = 16; size_t maxIterations = 16;
StackCompressor::run(*m_dialect, *m_object, true, maxIterations); // TODO: maxSwap, maxDup
StackCompressor::run(*m_dialect, *m_object, true, maxIterations, 16u, 16u);
BlockFlattener::run(*m_context, *m_ast); BlockFlattener::run(*m_context, *m_ast);
}}, }},
{"wordSizeTransform", [&]() { {"wordSizeTransform", [&]() {
@ -333,6 +334,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon(
}}, }},
{"fullSuite", [&]() { {"fullSuite", [&]() {
GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200); GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200);
// TODO: maxSwap, maxDup
OptimiserSuite::run( OptimiserSuite::run(
*m_dialect, *m_dialect,
&meter, &meter,
@ -340,15 +342,21 @@ YulOptimizerTestCommon::YulOptimizerTestCommon(
true, true,
frontend::OptimiserSettings::DefaultYulOptimiserSteps, frontend::OptimiserSettings::DefaultYulOptimiserSteps,
frontend::OptimiserSettings::DefaultYulOptimiserCleanupSteps, frontend::OptimiserSettings::DefaultYulOptimiserCleanupSteps,
frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment,
{},
16u,
16u
); );
}}, }},
{"stackLimitEvader", [&]() { {"stackLimitEvader", [&]() {
disambiguate(); disambiguate();
// TODO: maxSwap, maxDup
StackLimitEvader::run(*m_context, *m_object, CompilabilityChecker{ StackLimitEvader::run(*m_context, *m_object, CompilabilityChecker{
*m_dialect, *m_dialect,
*m_object, *m_object,
true true,
16u,
16u
}.unreachableVariables); }.unreachableVariables);
}}, }},
{"fakeStackLimitEvader", [&]() { {"fakeStackLimitEvader", [&]() {

View File

@ -189,7 +189,8 @@ void FuzzerUtil::testConstantOptimizer(string const& _input, bool _quiet)
for (bool isCreation: {false, true}) for (bool isCreation: {false, true})
{ {
Assembly assembly{isCreation, {}}; // TODO: versions
Assembly assembly{{}, {}, isCreation, {}};
for (u256 const& n: numbers) for (u256 const& n: numbers)
{ {
if (!_quiet) if (!_quiet)

View File

@ -222,7 +222,8 @@ public:
{ {
Object obj; Object obj;
obj.code = m_ast; obj.code = m_ast;
StackCompressor::run(m_dialect, obj, true, 16); // TODO maxSwap maxDup
StackCompressor::run(m_dialect, obj, true, 16, 16u, 16u);
break; break;
} }
default: default: