diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt index a6d4addc1..790aa3f9d 100644 --- a/test/tools/ossfuzz/CMakeLists.txt +++ b/test/tools/ossfuzz/CMakeLists.txt @@ -87,7 +87,14 @@ if (OSSFUZZ) set_target_properties(yul_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) - add_executable(yul_proto_diff_ossfuzz yulProto_diff_ossfuzz.cpp yulFuzzerCommon.cpp protoToYul.cpp yulProto.pb.cc) + add_executable( + yul_proto_diff_ossfuzz + yulProto_diff_ossfuzz.cpp + yulFuzzerCommon.cpp + protoToYul.cpp + yulProto.pb.cc + YulOptimizerStepTest.cpp + ) target_include_directories(yul_proto_diff_ossfuzz PRIVATE /usr/include/libprotobuf-mutator) target_link_libraries(yul_proto_diff_ossfuzz PRIVATE yul yulInterpreter @@ -104,6 +111,7 @@ if (OSSFUZZ) protoToYul.cpp yulProto.pb.cc protomutators/YulProtoMutator.cpp + YulOptimizerStepTest.cpp ) target_include_directories(yul_proto_diff_custom_mutate_ossfuzz PRIVATE /usr/include/libprotobuf-mutator) target_link_libraries(yul_proto_diff_custom_mutate_ossfuzz PRIVATE yul diff --git a/test/tools/ossfuzz/YulOptimizerStepTest.cpp b/test/tools/ossfuzz/YulOptimizerStepTest.cpp new file mode 100644 index 000000000..bccd64b93 --- /dev/null +++ b/test/tools/ossfuzz/YulOptimizerStepTest.cpp @@ -0,0 +1,367 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace solidity; +using namespace solidity::util; +using namespace solidity::langutil; +using namespace solidity::yul; +using namespace solidity::yul::test; +using namespace solidity::frontend; +using namespace solidity::frontend::test; +using namespace std; + +YulOptimizerStepTest::YulOptimizerStepTest( + shared_ptr _obj, + Dialect const& _dialect, + string const& _optimizerStep +) +{ + m_object = _obj; + m_ast = m_object->code; + m_analysisInfo = m_object->analysisInfo; + m_dialect = &_dialect; + m_optimizerStep = _optimizerStep; +} + +shared_ptr YulOptimizerStepTest::run() +{ + soltestAssert(m_dialect, "Dialect not set."); + + updateContext(); + + if (m_optimizerStep == "disambiguator") + disambiguate(); + else if (m_optimizerStep == "nameDisplacer") + { + disambiguate(); + NameDisplacer{ + *m_nameDispenser, + {"illegal1"_yulstring, "illegal2"_yulstring, "illegal3"_yulstring, "illegal4"_yulstring, "illegal5"_yulstring} + }(*m_ast); + } + else if (m_optimizerStep == "blockFlattener") + { + disambiguate(); + BlockFlattener::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "constantOptimiser") + { + GasMeter meter(dynamic_cast(*m_dialect), false, 200); + ConstantOptimiser{dynamic_cast(*m_dialect), meter}(*m_ast); + } + else if (m_optimizerStep == "varDeclInitializer") + VarDeclInitializer::run(*m_context, *m_ast); + else if (m_optimizerStep == "varNameCleaner") + { + FunctionHoister::run(*m_context, *m_ast); + VarNameCleaner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "forLoopConditionIntoBody") + { + disambiguate(); + ForLoopConditionIntoBody::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "forLoopInitRewriter") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "commonSubexpressionEliminator") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + CommonSubexpressionEliminator::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "conditionalUnsimplifier") + { + disambiguate(); + ConditionalUnsimplifier::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "conditionalSimplifier") + { + disambiguate(); + ConditionalSimplifier::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "expressionSplitter") + ExpressionSplitter::run(*m_context, *m_ast); + else if (m_optimizerStep == "expressionJoiner") + { + disambiguate(); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "splitJoin") + { + disambiguate(); + ExpressionSplitter::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "functionGrouper") + { + disambiguate(); + FunctionGrouper::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "functionHoister") + { + disambiguate(); + FunctionHoister::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "expressionInliner") + { + disambiguate(); + ExpressionInliner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "fullInliner") + { + disambiguate(); + FunctionHoister::run(*m_context, *m_ast); + FunctionGrouper::run(*m_context, *m_ast); + ExpressionSplitter::run(*m_context, *m_ast); + FullInliner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "mainFunction") + { + disambiguate(); + FunctionGrouper::run(*m_context, *m_ast); + MainFunction::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "rematerialiser") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + Rematerialiser::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "expressionSimplifier") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "fullSimplify") + { + disambiguate(); + ExpressionSplitter::run(*m_context, *m_ast); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + CommonSubexpressionEliminator::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + UnusedPruner::run(*m_context, *m_ast); + CircularReferencesPruner::run(*m_context, *m_ast); + DeadCodeEliminator::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "unusedPruner") + { + disambiguate(); + UnusedPruner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "circularReferencesPruner") + { + disambiguate(); + FunctionHoister::run(*m_context, *m_ast); + CircularReferencesPruner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "deadCodeEliminator") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + DeadCodeEliminator::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "ssaTransform") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + SSATransform::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "redundantAssignEliminator") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + RedundantAssignEliminator::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "ssaPlusCleanup") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + SSATransform::run(*m_context, *m_ast); + RedundantAssignEliminator::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "loadResolver") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + ExpressionSplitter::run(*m_context, *m_ast); + CommonSubexpressionEliminator::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + + LoadResolver::run(*m_context, *m_ast); + + UnusedPruner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "loopInvariantCodeMotion") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + LoopInvariantCodeMotion::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "controlFlowSimplifier") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + ControlFlowSimplifier::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "structuralSimplifier") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + LiteralRematerialiser::run(*m_context, *m_ast); + StructuralSimplifier::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "equivalentFunctionCombiner") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + EquivalentFunctionCombiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "ssaReverser") + { + disambiguate(); + SSAReverser::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "ssaAndBack") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + // apply SSA + SSATransform::run(*m_context, *m_ast); + RedundantAssignEliminator::run(*m_context, *m_ast); + // reverse SSA + SSAReverser::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + CommonSubexpressionEliminator::run(*m_context, *m_ast); + UnusedPruner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "stackCompressor") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + FunctionGrouper::run(*m_context, *m_ast); + size_t maxIterations = 16; + StackCompressor::run(*m_dialect, *m_object, true, maxIterations); + BlockFlattener::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "wordSizeTransform") + { + disambiguate(); + ExpressionSplitter::run(*m_context, *m_ast); + WordSizeTransform::run(*m_dialect, *m_dialect, *m_ast, *m_nameDispenser); + } + else if (m_optimizerStep == "fullSuite") + { + GasMeter meter(dynamic_cast(*m_dialect), false, 200); + OptimiserSuite::run(*m_dialect, &meter, *m_object, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps); + } + else + solUnimplemented("Invalid optimization step"); + +#if 0 + std::cout << AsmPrinter{*m_dialect}(*m_ast) << std::endl; +#endif + + return m_ast; +} + +void YulOptimizerStepTest::disambiguate() +{ + *m_ast = std::get(Disambiguator(*m_dialect, *m_analysisInfo)(*m_ast)); + m_analysisInfo.reset(); + updateContext(); +} + +void YulOptimizerStepTest::updateContext() +{ + m_nameDispenser = make_unique(*m_dialect, *m_ast, m_reservedIdentifiers); + m_context = make_unique(OptimiserStepContext{ + *m_dialect, + *m_nameDispenser, + m_reservedIdentifiers + }); +} diff --git a/test/tools/ossfuzz/YulOptimizerStepTest.h b/test/tools/ossfuzz/YulOptimizerStepTest.h new file mode 100644 index 000000000..db5673181 --- /dev/null +++ b/test/tools/ossfuzz/YulOptimizerStepTest.h @@ -0,0 +1,73 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ + +#pragma once + +#include +#include + +#include + +#include +#include + +namespace solidity::langutil +{ +class Scanner; +class Error; +using ErrorList = std::vector>; +class EVMVersion; +} + +namespace solidity::yul +{ +struct AsmAnalysisInfo; +struct Block; +struct Dialect; +struct Object; +} + +namespace solidity::yul::test +{ + +class YulOptimizerStepTest +{ +public: + explicit YulOptimizerStepTest( + std::shared_ptr _obj, + Dialect const& _dialect, + std::string const& _optimizerStep + ); + std::shared_ptr run(); + +private: + void disambiguate(); + void updateContext(); + + std::string m_optimizerStep; + + Dialect const* m_dialect = nullptr; + std::set m_reservedIdentifiers; + std::unique_ptr m_nameDispenser; + std::unique_ptr m_context; + + std::shared_ptr m_ast; + std::shared_ptr m_analysisInfo; + std::shared_ptr m_object; +}; + +} diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index aeb8fc665..9dc6cfbac 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -1905,6 +1905,87 @@ void ProtoConverter::buildObjectScopeTree(Object const& _x) m_objectScope.emplace(objectName, node); } +string ProtoConverter::optStepToString(Program_OptimizerStep const& _x) +{ + switch (_x) + { + case Program_OptimizerStep_FULLSUITE: + return "fullSuite"; + case Program_OptimizerStep_DISAMBIGUATOR: + return "disambiguator"; + case Program_OptimizerStep_NAMEDISPLACER: + return "nameDisplacer"; + case Program_OptimizerStep_BLOCKFLATTENER: + return "blockFlattener"; + case Program_OptimizerStep_CONSTANTOPTIMISER: + return "constantOptimiser"; + case Program_OptimizerStep_VARDECLINITIALIZER: + return "varDeclInitializer"; + case Program_OptimizerStep_VARNAMECLEANER: + return "varNameCleaner"; + case Program_OptimizerStep_FORLOOPCONDITIONINTOBODY: + return "forLoopConditionIntoBody"; + case Program_OptimizerStep_FORLOOPINITREWRITER: + return "forLoopInitRewriter"; + case Program_OptimizerStep_COMMONSUBEXPRESSIONELIMINATOR: + return "commonSubexpressionEliminator"; + case Program_OptimizerStep_CONDITIONALUNSIMPLIFIER: + return "conditionalUnsimplifier"; + case Program_OptimizerStep_CONDITIONALSIMPLIFIER: + return "conditionalSimplifier"; + case Program_OptimizerStep_EXPRESSIONSPLITTER: + return "expressionSplitter"; + case Program_OptimizerStep_EXPRESSIONJOINER: + return "expressionJoiner"; + case Program_OptimizerStep_SPLITJOIN: + return "splitJoin"; + case Program_OptimizerStep_FUNCTIONGROUPER: + return "functionGrouper"; + case Program_OptimizerStep_FUNCTIONHOISTER: + return "functionHoister"; + case Program_OptimizerStep_EXPRESSIONINLINER: + return "expressionInliner"; + case Program_OptimizerStep_FULLINLINER: + return "fullInliner"; + case Program_OptimizerStep_REMATERIALISER: + return "rematerialiser"; + case Program_OptimizerStep_EXPRESSIONSIMPLIFIER: + return "expressionSimplifier"; + case Program_OptimizerStep_FULLSIMPLIFY: + return "fullSimplify"; + case Program_OptimizerStep_UNUSEDPRUNER: + return "unusedPruner"; + case Program_OptimizerStep_CIRCULARREFERENCESPRUNER: + return "circularReferencesPruner"; + case Program_OptimizerStep_DEADCODEELIMINATOR: + return "deadCodeEliminator"; + case Program_OptimizerStep_SSATRANSFORM: + return "ssaTransform"; + case Program_OptimizerStep_REDUNDANTASSIGNELIMINATOR: + return "redundantAssignEliminator"; + case Program_OptimizerStep_SSAPLUSCLEANUP: + return "ssaPlusCleanup"; + case Program_OptimizerStep_LOADRESOLVER: + return "loadResolver"; + case Program_OptimizerStep_LOOPINVARIANTCODEMOTION: + return "loopInvariantCodeMotion"; + case Program_OptimizerStep_CONTROLFLOWSIMPLIFIER: + return "controlFlowSimplifier"; + case Program_OptimizerStep_STRUCTURALSIMPLIFIER: + return "structuralSimplifier"; + case Program_OptimizerStep_EQUIVALENTFUNCTIONCOMBINER: + return "equivalentFunctionCombiner"; + case Program_OptimizerStep_SSAREVERSER: + return "ssaReverser"; + case Program_OptimizerStep_SSAANDBACK: + return "ssaAndBack"; + case Program_OptimizerStep_STACKCOMPRESSION: + return "stackCompressor"; + default: + return "fullSuite"; + } +} + void ProtoConverter::visit(Program const& _x) { // Initialize input size @@ -1913,6 +1994,9 @@ void ProtoConverter::visit(Program const& _x) // Record EVM Version m_evmVersion = evmVersionMapping(_x.ver()); + // Record optimizer step + m_optimizerStep = optStepToString(_x.step()); + // Program is either a Yul object or a block of // statements. switch (_x.program_oneof_case()) diff --git a/test/tools/ossfuzz/protoToYul.h b/test/tools/ossfuzz/protoToYul.h index bf9963726..2968b8abd 100644 --- a/test/tools/ossfuzz/protoToYul.h +++ b/test/tools/ossfuzz/protoToYul.h @@ -65,6 +65,12 @@ public: return m_evmVersion; } + /// Returns optimizer step string + std::string optStepString() + { + return m_optimizerStep; + } + private: void visit(BinaryOp const&); @@ -291,6 +297,9 @@ private: /// enum of type Program_Version solidity::langutil::EVMVersion evmVersionMapping(Program_Version const& _x); + /// Returns string representation of an optimization step. + std::string optStepToString(Program_OptimizerStep const& _x); + /// Returns a monotonically increasing counter that starts from zero. unsigned counter() { @@ -390,5 +399,7 @@ private: bool m_forInitScopeExtEnabled; /// Object that holds the targeted evm version specified by protobuf input solidity::langutil::EVMVersion m_evmVersion; + /// Optimizer step + std::string m_optimizerStep; }; } diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp index d977c7761..32387b844 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.cpp +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -63,7 +63,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( } catch (ExpressionNestingLimitReached const&) { - reason = TerminationReason::ExpresionNestingLimitReached; + reason = TerminationReason::ExpressionNestingLimitReached; } catch (ExplicitlyTerminated const&) { diff --git a/test/tools/ossfuzz/yulFuzzerCommon.h b/test/tools/ossfuzz/yulFuzzerCommon.h index a32c75705..08ce47f2a 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.h +++ b/test/tools/ossfuzz/yulFuzzerCommon.h @@ -28,7 +28,7 @@ struct yulFuzzerUtil ExplicitlyTerminated, StepLimitReached, TraceLimitReached, - ExpresionNestingLimitReached, + ExpressionNestingLimitReached, None }; diff --git a/test/tools/ossfuzz/yulProto.proto b/test/tools/ossfuzz/yulProto.proto index 00ddc329d..5eb3e6824 100644 --- a/test/tools/ossfuzz/yulProto.proto +++ b/test/tools/ossfuzz/yulProto.proto @@ -410,11 +410,50 @@ message Program { ISTANBUL = 6; BERLIN = 7; } + enum OptimizerStep { + FULLSUITE = 0; + DISAMBIGUATOR = 1; + NAMEDISPLACER = 2; + BLOCKFLATTENER = 3; + CONSTANTOPTIMISER = 4; + VARDECLINITIALIZER = 5; + VARNAMECLEANER = 6; + FORLOOPCONDITIONINTOBODY = 7; + FORLOOPINITREWRITER = 8; + COMMONSUBEXPRESSIONELIMINATOR = 9; + CONDITIONALUNSIMPLIFIER = 10; + CONDITIONALSIMPLIFIER = 11; + EXPRESSIONSPLITTER = 12; + EXPRESSIONJOINER = 13; + SPLITJOIN = 14; + FUNCTIONGROUPER = 15; + FUNCTIONHOISTER = 16; + EXPRESSIONINLINER = 17; + FULLINLINER = 18; + REMATERIALISER = 19; + EXPRESSIONSIMPLIFIER = 20; + FULLSIMPLIFY = 21; + UNUSEDPRUNER = 22; + CIRCULARREFERENCESPRUNER = 23; + DEADCODEELIMINATOR = 24; + SSATRANSFORM = 25; + REDUNDANTASSIGNELIMINATOR = 26; + SSAPLUSCLEANUP = 27; + LOADRESOLVER = 28; + LOOPINVARIANTCODEMOTION = 29; + CONTROLFLOWSIMPLIFIER = 30; + STRUCTURALSIMPLIFIER = 31; + EQUIVALENTFUNCTIONCOMBINER = 32; + SSAREVERSER = 33; + SSAANDBACK = 34; + STACKCOMPRESSION = 35; + } oneof program_oneof { Block block = 1; Object obj = 2; } required Version ver = 3; + required OptimizerStep step = 4; } package solidity.yul.test.yul_fuzzer; diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index 2ee2b702e..5191c7e5a 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -59,6 +60,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) ProtoConverter converter; string yul_source = converter.programToString(_input); EVMVersion version = converter.version(); + string optStep = converter.optStepString(); if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { @@ -91,24 +93,29 @@ DEFINE_PROTO_FUZZER(Program const& _input) ostringstream os1; ostringstream os2; + auto const& evmDialect = EVMDialect::strictAssemblyForEVMObjects(version); yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, stack.parserResult()->code, - EVMDialect::strictAssemblyForEVMObjects(version) + evmDialect ); if ( termReason == yulFuzzerUtil::TerminationReason::StepLimitReached || - termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached || - termReason == yulFuzzerUtil::TerminationReason::ExpresionNestingLimitReached + termReason == yulFuzzerUtil::TerminationReason::ExpressionNestingLimitReached || + termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached ) - return; + return; - stack.optimize(); + YulOptimizerStepTest optimizerStepTest( + stack.parserResult(), + evmDialect, + optStep + ); termReason = yulFuzzerUtil::interpret( os2, - stack.parserResult()->code, - EVMDialect::strictAssemblyForEVMObjects(version) + optimizerStepTest.run(), + evmDialect ); if ( termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||