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})
|
||||
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
|
||||
|
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);
|
||||
}
|
||||
|
||||
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())
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret(
|
||||
}
|
||||
catch (ExpressionNestingLimitReached const&)
|
||||
{
|
||||
reason = TerminationReason::ExpresionNestingLimitReached;
|
||||
reason = TerminationReason::ExpressionNestingLimitReached;
|
||||
}
|
||||
catch (ExplicitlyTerminated const&)
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ struct yulFuzzerUtil
|
||||
ExplicitlyTerminated,
|
||||
StepLimitReached,
|
||||
TraceLimitReached,
|
||||
ExpresionNestingLimitReached,
|
||||
ExpressionNestingLimitReached,
|
||||
None
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <fstream>
|
||||
|
||||
#include <test/tools/ossfuzz/yulProto.pb.h>
|
||||
#include <test/tools/ossfuzz/YulOptimizerStepTest.h>
|
||||
#include <test/tools/fuzzer_common.h>
|
||||
#include <test/tools/ossfuzz/protoToYul.h>
|
||||
#include <src/libfuzzer/libfuzzer_macro.h>
|
||||
@ -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 ||
|
||||
|
Loading…
Reference in New Issue
Block a user