mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Fuzzer: Enable fine-grained yul optimizer fuzzing
This commit is contained in:
parent
24f0f3bb16
commit
3b3c64efe2
@ -87,7 +87,14 @@ if (OSSFUZZ)
|
|||||||
set_target_properties(yul_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
set_target_properties(yul_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||||
target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion)
|
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_include_directories(yul_proto_diff_ossfuzz PRIVATE /usr/include/libprotobuf-mutator)
|
||||||
target_link_libraries(yul_proto_diff_ossfuzz PRIVATE yul
|
target_link_libraries(yul_proto_diff_ossfuzz PRIVATE yul
|
||||||
yulInterpreter
|
yulInterpreter
|
||||||
@ -104,6 +111,7 @@ if (OSSFUZZ)
|
|||||||
protoToYul.cpp
|
protoToYul.cpp
|
||||||
yulProto.pb.cc
|
yulProto.pb.cc
|
||||||
protomutators/YulProtoMutator.cpp
|
protomutators/YulProtoMutator.cpp
|
||||||
|
YulOptimizerStepTest.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(yul_proto_diff_custom_mutate_ossfuzz PRIVATE /usr/include/libprotobuf-mutator)
|
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
|
target_link_libraries(yul_proto_diff_custom_mutate_ossfuzz PRIVATE yul
|
||||||
|
|||||||
367
test/tools/ossfuzz/YulOptimizerStepTest.cpp
Normal file
367
test/tools/ossfuzz/YulOptimizerStepTest.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <test/tools/ossfuzz/YulOptimizerStepTest.h>
|
||||||
|
|
||||||
|
#include <test/libsolidity/util/SoltestErrors.h>
|
||||||
|
|
||||||
|
#include <libyul/optimiser/BlockFlattener.h>
|
||||||
|
#include <libyul/optimiser/VarDeclInitializer.h>
|
||||||
|
#include <libyul/optimiser/VarNameCleaner.h>
|
||||||
|
#include <libyul/optimiser/ControlFlowSimplifier.h>
|
||||||
|
#include <libyul/optimiser/DeadCodeEliminator.h>
|
||||||
|
#include <libyul/optimiser/Disambiguator.h>
|
||||||
|
#include <libyul/optimiser/CircularReferencesPruner.h>
|
||||||
|
#include <libyul/optimiser/ConditionalUnsimplifier.h>
|
||||||
|
#include <libyul/optimiser/ConditionalSimplifier.h>
|
||||||
|
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
|
||||||
|
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
|
||||||
|
#include <libyul/optimiser/ExpressionSplitter.h>
|
||||||
|
#include <libyul/optimiser/FunctionGrouper.h>
|
||||||
|
#include <libyul/optimiser/FunctionHoister.h>
|
||||||
|
#include <libyul/optimiser/ExpressionInliner.h>
|
||||||
|
#include <libyul/optimiser/FullInliner.h>
|
||||||
|
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
||||||
|
#include <libyul/optimiser/ForLoopInitRewriter.h>
|
||||||
|
#include <libyul/optimiser/LoadResolver.h>
|
||||||
|
#include <libyul/optimiser/LoopInvariantCodeMotion.h>
|
||||||
|
#include <libyul/optimiser/MainFunction.h>
|
||||||
|
#include <libyul/optimiser/NameDisplacer.h>
|
||||||
|
#include <libyul/optimiser/Rematerialiser.h>
|
||||||
|
#include <libyul/optimiser/ExpressionSimplifier.h>
|
||||||
|
#include <libyul/optimiser/UnusedPruner.h>
|
||||||
|
#include <libyul/optimiser/ExpressionJoiner.h>
|
||||||
|
#include <libyul/optimiser/OptimiserStep.h>
|
||||||
|
#include <libyul/optimiser/SSAReverser.h>
|
||||||
|
#include <libyul/optimiser/SSATransform.h>
|
||||||
|
#include <libyul/optimiser/RedundantAssignEliminator.h>
|
||||||
|
#include <libyul/optimiser/StructuralSimplifier.h>
|
||||||
|
#include <libyul/optimiser/StackCompressor.h>
|
||||||
|
#include <libyul/optimiser/Suite.h>
|
||||||
|
#include <libyul/backends/evm/ConstantOptimiser.h>
|
||||||
|
#include <libyul/backends/evm/EVMDialect.h>
|
||||||
|
#include <libyul/backends/evm/EVMMetrics.h>
|
||||||
|
#include <libyul/backends/wasm/WordSizeTransform.h>
|
||||||
|
#include <libyul/AsmPrinter.h>
|
||||||
|
#include <libyul/AsmAnalysis.h>
|
||||||
|
#include <libyul/AssemblyStack.h>
|
||||||
|
#include <liblangutil/SourceReferenceFormatter.h>
|
||||||
|
|
||||||
|
#include <libsolidity/interface/OptimiserSettings.h>
|
||||||
|
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
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<Object> _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<Block> 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<EVMDialect const&>(*m_dialect), false, 200);
|
||||||
|
ConstantOptimiser{dynamic_cast<EVMDialect const&>(*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<EVMDialect const&>(*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<Block>(Disambiguator(*m_dialect, *m_analysisInfo)(*m_ast));
|
||||||
|
m_analysisInfo.reset();
|
||||||
|
updateContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void YulOptimizerStepTest::updateContext()
|
||||||
|
{
|
||||||
|
m_nameDispenser = make_unique<NameDispenser>(*m_dialect, *m_ast, m_reservedIdentifiers);
|
||||||
|
m_context = make_unique<OptimiserStepContext>(OptimiserStepContext{
|
||||||
|
*m_dialect,
|
||||||
|
*m_nameDispenser,
|
||||||
|
m_reservedIdentifiers
|
||||||
|
});
|
||||||
|
}
|
||||||
73
test/tools/ossfuzz/YulOptimizerStepTest.h
Normal file
73
test/tools/ossfuzz/YulOptimizerStepTest.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libyul/optimiser/OptimiserStep.h>
|
||||||
|
#include <libyul/optimiser/NameDispenser.h>
|
||||||
|
|
||||||
|
#include <libyul/YulString.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace solidity::langutil
|
||||||
|
{
|
||||||
|
class Scanner;
|
||||||
|
class Error;
|
||||||
|
using ErrorList = std::vector<std::shared_ptr<Error const>>;
|
||||||
|
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<Object> _obj,
|
||||||
|
Dialect const& _dialect,
|
||||||
|
std::string const& _optimizerStep
|
||||||
|
);
|
||||||
|
std::shared_ptr<Block> run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void disambiguate();
|
||||||
|
void updateContext();
|
||||||
|
|
||||||
|
std::string m_optimizerStep;
|
||||||
|
|
||||||
|
Dialect const* m_dialect = nullptr;
|
||||||
|
std::set<YulString> m_reservedIdentifiers;
|
||||||
|
std::unique_ptr<NameDispenser> m_nameDispenser;
|
||||||
|
std::unique_ptr<OptimiserStepContext> m_context;
|
||||||
|
|
||||||
|
std::shared_ptr<Block> m_ast;
|
||||||
|
std::shared_ptr<AsmAnalysisInfo> m_analysisInfo;
|
||||||
|
std::shared_ptr<Object> m_object;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@ -1905,6 +1905,87 @@ void ProtoConverter::buildObjectScopeTree(Object const& _x)
|
|||||||
m_objectScope.emplace(objectName, node);
|
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)
|
void ProtoConverter::visit(Program const& _x)
|
||||||
{
|
{
|
||||||
// Initialize input size
|
// Initialize input size
|
||||||
@ -1913,6 +1994,9 @@ void ProtoConverter::visit(Program const& _x)
|
|||||||
// Record EVM Version
|
// Record EVM Version
|
||||||
m_evmVersion = evmVersionMapping(_x.ver());
|
m_evmVersion = evmVersionMapping(_x.ver());
|
||||||
|
|
||||||
|
// Record optimizer step
|
||||||
|
m_optimizerStep = optStepToString(_x.step());
|
||||||
|
|
||||||
// Program is either a Yul object or a block of
|
// Program is either a Yul object or a block of
|
||||||
// statements.
|
// statements.
|
||||||
switch (_x.program_oneof_case())
|
switch (_x.program_oneof_case())
|
||||||
|
|||||||
@ -65,6 +65,12 @@ public:
|
|||||||
return m_evmVersion;
|
return m_evmVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns optimizer step string
|
||||||
|
std::string optStepString()
|
||||||
|
{
|
||||||
|
return m_optimizerStep;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void visit(BinaryOp const&);
|
void visit(BinaryOp const&);
|
||||||
|
|
||||||
@ -291,6 +297,9 @@ private:
|
|||||||
/// enum of type Program_Version
|
/// enum of type Program_Version
|
||||||
solidity::langutil::EVMVersion evmVersionMapping(Program_Version const& _x);
|
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.
|
/// Returns a monotonically increasing counter that starts from zero.
|
||||||
unsigned counter()
|
unsigned counter()
|
||||||
{
|
{
|
||||||
@ -390,5 +399,7 @@ private:
|
|||||||
bool m_forInitScopeExtEnabled;
|
bool m_forInitScopeExtEnabled;
|
||||||
/// Object that holds the targeted evm version specified by protobuf input
|
/// Object that holds the targeted evm version specified by protobuf input
|
||||||
solidity::langutil::EVMVersion m_evmVersion;
|
solidity::langutil::EVMVersion m_evmVersion;
|
||||||
|
/// Optimizer step
|
||||||
|
std::string m_optimizerStep;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret(
|
|||||||
}
|
}
|
||||||
catch (ExpressionNestingLimitReached const&)
|
catch (ExpressionNestingLimitReached const&)
|
||||||
{
|
{
|
||||||
reason = TerminationReason::ExpresionNestingLimitReached;
|
reason = TerminationReason::ExpressionNestingLimitReached;
|
||||||
}
|
}
|
||||||
catch (ExplicitlyTerminated const&)
|
catch (ExplicitlyTerminated const&)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -28,7 +28,7 @@ struct yulFuzzerUtil
|
|||||||
ExplicitlyTerminated,
|
ExplicitlyTerminated,
|
||||||
StepLimitReached,
|
StepLimitReached,
|
||||||
TraceLimitReached,
|
TraceLimitReached,
|
||||||
ExpresionNestingLimitReached,
|
ExpressionNestingLimitReached,
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -410,11 +410,50 @@ message Program {
|
|||||||
ISTANBUL = 6;
|
ISTANBUL = 6;
|
||||||
BERLIN = 7;
|
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 {
|
oneof program_oneof {
|
||||||
Block block = 1;
|
Block block = 1;
|
||||||
Object obj = 2;
|
Object obj = 2;
|
||||||
}
|
}
|
||||||
required Version ver = 3;
|
required Version ver = 3;
|
||||||
|
required OptimizerStep step = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
package solidity.yul.test.yul_fuzzer;
|
package solidity.yul.test.yul_fuzzer;
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <test/tools/ossfuzz/yulProto.pb.h>
|
#include <test/tools/ossfuzz/yulProto.pb.h>
|
||||||
|
#include <test/tools/ossfuzz/YulOptimizerStepTest.h>
|
||||||
#include <test/tools/fuzzer_common.h>
|
#include <test/tools/fuzzer_common.h>
|
||||||
#include <test/tools/ossfuzz/protoToYul.h>
|
#include <test/tools/ossfuzz/protoToYul.h>
|
||||||
#include <src/libfuzzer/libfuzzer_macro.h>
|
#include <src/libfuzzer/libfuzzer_macro.h>
|
||||||
@ -59,6 +60,7 @@ DEFINE_PROTO_FUZZER(Program const& _input)
|
|||||||
ProtoConverter converter;
|
ProtoConverter converter;
|
||||||
string yul_source = converter.programToString(_input);
|
string yul_source = converter.programToString(_input);
|
||||||
EVMVersion version = converter.version();
|
EVMVersion version = converter.version();
|
||||||
|
string optStep = converter.optStepString();
|
||||||
|
|
||||||
if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
|
if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
|
||||||
{
|
{
|
||||||
@ -91,24 +93,29 @@ DEFINE_PROTO_FUZZER(Program const& _input)
|
|||||||
|
|
||||||
ostringstream os1;
|
ostringstream os1;
|
||||||
ostringstream os2;
|
ostringstream os2;
|
||||||
|
auto const& evmDialect = EVMDialect::strictAssemblyForEVMObjects(version);
|
||||||
yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
|
yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
|
||||||
os1,
|
os1,
|
||||||
stack.parserResult()->code,
|
stack.parserResult()->code,
|
||||||
EVMDialect::strictAssemblyForEVMObjects(version)
|
evmDialect
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||
|
termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||
|
||||||
termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached ||
|
termReason == yulFuzzerUtil::TerminationReason::ExpressionNestingLimitReached ||
|
||||||
termReason == yulFuzzerUtil::TerminationReason::ExpresionNestingLimitReached
|
termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
stack.optimize();
|
YulOptimizerStepTest optimizerStepTest(
|
||||||
|
stack.parserResult(),
|
||||||
|
evmDialect,
|
||||||
|
optStep
|
||||||
|
);
|
||||||
termReason = yulFuzzerUtil::interpret(
|
termReason = yulFuzzerUtil::interpret(
|
||||||
os2,
|
os2,
|
||||||
stack.parserResult()->code,
|
optimizerStepTest.run(),
|
||||||
EVMDialect::strictAssemblyForEVMObjects(version)
|
evmDialect
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||
|
termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user