process some of the feedback

This commit is contained in:
Daniel Lupu 2022-11-26 19:32:50 +02:00 committed by r0qs
parent 5fd6b206a9
commit 4581139afa
No known key found for this signature in database
GPG Key ID: 61503DBA6667276C

View File

@ -88,15 +88,16 @@ public:
}.printErrorInformation(_errors); }.printErrorInformation(_errors);
} }
shared_ptr<Object> getSubObject(shared_ptr<Object> const& _object, string const& _qualifiedPath) /// Recursively searches for an object at @param _qualifiedPath within @param _object.
/// @returns the object at @param qualifiedPath or a nullptr if it was not found.
shared_ptr<Object> getObject(shared_ptr<Object> const& _object, string const& _qualifiedPath)
{ {
if (_qualifiedPath.empty() || _qualifiedPath == _object->name.str()) if (_qualifiedPath.empty() || _qualifiedPath == _object->name.str())
return _object; return _object;
yulAssert( if (!boost::algorithm::starts_with(_qualifiedPath, _object->name.str() + ".")) {
boost::algorithm::starts_with(_qualifiedPath, _object->name.str() + "."), return nullptr;
"Assembly object not found." }
);
string const subObjectPath = _qualifiedPath.substr(_object->name.str().length() + 1); string const subObjectPath = _qualifiedPath.substr(_object->name.str().length() + 1);
string const subObjectName = subObjectPath.substr(0, subObjectPath.find_first_of('.')); string const subObjectName = subObjectPath.substr(0, subObjectPath.find_first_of('.'));
@ -106,19 +107,18 @@ public:
[&subObjectName](auto const& _subObject) { return _subObject->name.str() == subObjectName; } [&subObjectName](auto const& _subObject) { return _subObject->name.str() == subObjectName; }
); );
yulAssert( if (subObjectIt == _object->subObjects.end()) {
subObjectIt != _object->subObjects.end(), return nullptr;
"Assembly object not found." }
);
auto subObject = dynamic_pointer_cast<Object>(*subObjectIt); auto subObject = dynamic_pointer_cast<Object>(*subObjectIt);
yulAssert( yulAssert(
subObject != nullptr, subObject != nullptr,
"Assembly object may not contain code." "Assembly object does not contain code."
); );
return getSubObject(subObject, subObjectPath); return getObject(subObject, subObjectPath);
} }
void parse(string const& _input, string const& _objectPath) void parse(string const& _input, string const& _objectPath)
@ -133,8 +133,8 @@ public:
auto scanner = make_shared<Scanner>(charStream); auto scanner = make_shared<Scanner>(charStream);
if (!m_inputWasCodeBlock && scanner->currentToken() == Token::LBrace) if (!m_inputIsCodeBlock && scanner->currentToken() == Token::LBrace)
m_inputWasCodeBlock = true; m_inputIsCodeBlock = true;
shared_ptr<Object> object = parser.parse(scanner, false); shared_ptr<Object> object = parser.parse(scanner, false);
@ -145,7 +145,12 @@ public:
throw runtime_error("Could not parse source."); throw runtime_error("Could not parse source.");
} }
m_object = getSubObject(object, _objectPath); m_object = getObject(object, _objectPath);
if (m_object == nullptr) {
throw runtime_error("Assembly object not found.");
}
runCodeAnalyzer(errorReporter); runCodeAnalyzer(errorReporter);
} }
catch(...) catch(...)
@ -205,22 +210,22 @@ public:
} }
} }
void applyFunctionToObject(shared_ptr<Object> _object, function<void(Object&)> _function) void applyFunctionToObjectAndSubobjects(Object& _object, function<void(Object&)> _function)
{ {
for (auto const& subObjectNode: _object->subObjects) { for (auto const& subObjectNode: _object.subObjects) {
auto subObject = dynamic_pointer_cast<Object>(subObjectNode); auto subObject = dynamic_pointer_cast<Object>(subObjectNode);
if (subObject != nullptr) if (subObject != nullptr)
applyFunctionToObject(subObject, _function); applyFunctionToObjectAndSubobjects(*subObject, _function);
} }
_function(*_object); _function(_object);
} }
void runCodeAnalyzer(ErrorReporter& _errorReporter) void runCodeAnalyzer(ErrorReporter& _errorReporter)
{ {
applyFunctionToObject( applyFunctionToObjectAndSubobjects(
m_object, *m_object,
[&](Object& _object) [&](Object& _object)
{ {
_object.analysisInfo = make_shared<yul::AsmAnalysisInfo>(); _object.analysisInfo = make_shared<yul::AsmAnalysisInfo>();
@ -241,8 +246,8 @@ public:
void runCodeDisambiguator() void runCodeDisambiguator()
{ {
applyFunctionToObject( applyFunctionToObjectAndSubobjects(
m_object, *m_object,
[&](Object& _object) [&](Object& _object)
{ {
_object.code = make_shared<yul::Block>( _object.code = make_shared<yul::Block>(
@ -256,8 +261,8 @@ public:
void runSequence(string_view _steps) void runSequence(string_view _steps)
{ {
applyFunctionToObject( applyFunctionToObjectAndSubobjects(
m_object, *m_object,
[&](Object& _object) [&](Object& _object)
{ {
OptimiserSuite{*m_context}.runSequence(_steps, *_object.code); OptimiserSuite{*m_context}.runSequence(_steps, *_object.code);
@ -267,8 +272,8 @@ public:
void runVarNameCleaner() void runVarNameCleaner()
{ {
applyFunctionToObject( applyFunctionToObjectAndSubobjects(
m_object, *m_object,
[&](Object& _object) [&](Object& _object)
{ {
VarNameCleaner::run(*m_context, *_object.code); VarNameCleaner::run(*m_context, *_object.code);
@ -278,8 +283,8 @@ public:
void runStackCompressor() void runStackCompressor()
{ {
applyFunctionToObject( applyFunctionToObjectAndSubobjects(
m_object, *m_object,
[&](Object& _object) [&](Object& _object)
{ {
StackCompressor::run(m_dialect, _object, true, 16); StackCompressor::run(m_dialect, _object, true, 16);
@ -287,18 +292,12 @@ public:
); );
} }
void parseAndPrint(string _source, string _objectPath)
{
parse(_source, _objectPath);
printObject();
}
void printObject() void printObject()
{ {
if (!m_inputWasCodeBlock) if (!m_inputIsCodeBlock)
cout << m_object->toString(&m_dialect) << endl; cout << m_object->toString(&m_dialect) << endl;
else else
cout << AsmPrinter{m_dialect}(*m_object->code) << endl; cout << AsmPrinter{m_dialect}(*m_object->code) << endl;
} }
void resetNameDispenser() void resetNameDispenser()
@ -318,7 +317,7 @@ public:
); );
} }
void runSteps(string _source, string _objectPath, string _steps) void parseAndRunSteps(string const& _source, string const& _objectPath, string const& _steps)
{ {
parse(_source, _objectPath); parse(_source, _objectPath);
runCodeDisambiguator(); runCodeDisambiguator();
@ -384,7 +383,7 @@ public:
private: private:
shared_ptr<yul::Object> m_object; shared_ptr<yul::Object> m_object;
bool m_inputWasCodeBlock = false; bool m_inputIsCodeBlock = false;
Dialect const& m_dialect{EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; Dialect const& m_dialect{EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})};
set<YulString> const m_reservedIdentifiers = {}; set<YulString> const m_reservedIdentifiers = {};
@ -410,11 +409,10 @@ int main(int argc, char** argv)
po::options_description options( po::options_description options(
R"(yulopti, yul optimizer exploration tool. R"(yulopti, yul optimizer exploration tool.
Usage: yulopti [Options] <file> Usage: yulopti [Options] <file>
Reads <file> containing a yul object and applies optimizer steps to it, Reads <file> containing a either a yul object or a yul code block and applies optimizer steps to it,
interactively read from stdin. interactively read from stdin.
In non-interactive mode a list of steps has to be provided. In non-interactive mode a list of steps has to be provided.
If <file> is -, yul code is read from stdin and run non-interactively. If <file> is -, yul code is read from stdin and run non-interactively.
An <object> flag may be provided, specifying a dotted path to an object in the input.
Allowed options)", Allowed options)",
po::options_description::m_default_line_length, po::options_description::m_default_line_length,
@ -432,8 +430,10 @@ int main(int argc, char** argv)
) )
( (
"object", "object",
po::value<string>(), po::value<string>()->value_name("path"),
"path to a yul object in the input" "Dotted path to a specific Yul object in the source. "
"If not specified, the top-level object is used. "
"Only valid if the source actually contains objects (rather than a block of Yul code)."
) )
( (
"non-interactive,n", "non-interactive,n",
@ -491,14 +491,17 @@ int main(int argc, char** argv)
bool disambiguated = false; bool disambiguated = false;
if (!nonInteractive) if (!nonInteractive)
yulOpti.parseAndPrint(input, objectPath); {
yulOpti.parse(input, objectPath);
yulOpti.printObject();
}
if (arguments.count("steps")) if (arguments.count("steps"))
{ {
string sequence = arguments["steps"].as<string>(); string sequence = arguments["steps"].as<string>();
if (!nonInteractive) if (!nonInteractive)
cout << "----------------------" << endl; cout << "----------------------" << endl;
yulOpti.runSteps(input, objectPath, sequence); yulOpti.parseAndRunSteps(input, objectPath, sequence);
disambiguated = true; disambiguated = true;
} }
if (!nonInteractive) if (!nonInteractive)