From 2a5280faa0cc001f76716fa1638ac8de8caf9430 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 9 Jul 2019 14:06:33 +0200 Subject: [PATCH 1/2] Check availability of data objects already in analysis phase. --- Changelog.md | 1 + libyul/AsmAnalysis.cpp | 18 +++++++++---- libyul/AsmAnalysis.h | 8 ++++-- libyul/AssemblyStack.cpp | 15 ++++++++++- test/libyul/ObjectParser.cpp | 13 +++++++++ .../object_access.yul | 27 ++++++++++--------- .../expressionSplitter/object_access.yul | 17 +++++++----- 7 files changed, 72 insertions(+), 27 deletions(-) diff --git a/Changelog.md b/Changelog.md index 098be7003..74f5979ad 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,6 +18,7 @@ Compiler Features: Bugfixes: * View/Pure Checker: Properly detect state variable access through base class. + * Yul analyzer: Check availability of data objects already in analysis phase. diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index ef6c8706c..abc1f9bee 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -383,11 +383,19 @@ bool AsmAnalyzer::operator()(FunctionCall const& _funCall) { if (!expectExpression(arg)) success = false; - else if (needsLiteralArguments && arg.type() != typeid(Literal)) - m_errorReporter.typeError( - _funCall.functionName.location, - "Function expects direct literals as arguments." - ); + else if (needsLiteralArguments) + { + if (arg.type() != typeid(Literal)) + m_errorReporter.typeError( + _funCall.functionName.location, + "Function expects direct literals as arguments." + ); + else if (!m_dataNames.count(boost::get(arg).value)) + m_errorReporter.typeError( + _funCall.functionName.location, + "Unknown data object \"" + boost::get(arg).value.str() + "\"." + ); + } } // Use argument size instead of parameter count to avoid misleading errors. m_stackHeight += int(returns) - int(_funCall.arguments.size()); diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 2834c3cb7..b07da7099 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -61,13 +61,15 @@ public: langutil::ErrorReporter& _errorReporter, boost::optional _errorTypeForLoose, Dialect const& _dialect, - ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver() + ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver(), + std::set const& _dataNames = {} ): m_resolver(_resolver), m_info(_analysisInfo), m_errorReporter(_errorReporter), m_dialect(_dialect), - m_errorTypeForLoose(_errorTypeForLoose) + m_errorTypeForLoose(_errorTypeForLoose), + m_dataNames(_dataNames) { if (EVMDialect const* evmDialect = dynamic_cast(&m_dialect)) m_evmVersion = evmDialect->evmVersion(); @@ -124,6 +126,8 @@ private: langutil::EVMVersion m_evmVersion; Dialect const& m_dialect; boost::optional m_errorTypeForLoose; + /// Names of data objects to be referenced by builtin functions with literal arguments. + std::set m_dataNames; ForLoop const* m_currentForLoop = nullptr; }; diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp index 549a599fe..023048029 100644 --- a/libyul/AssemblyStack.cpp +++ b/libyul/AssemblyStack.cpp @@ -113,7 +113,20 @@ bool AssemblyStack::analyzeParsed(Object& _object) { solAssert(_object.code, ""); _object.analysisInfo = make_shared(); - AsmAnalyzer analyzer(*_object.analysisInfo, m_errorReporter, boost::none, languageToDialect(m_language, m_evmVersion)); + + set objectNames; + objectNames.insert(_object.name); + for (auto const& subObject: _object.subIndexByName) + objectNames.insert(subObject.first); + + AsmAnalyzer analyzer( + *_object.analysisInfo, + m_errorReporter, + boost::none, + languageToDialect(m_language, m_evmVersion), + {}, + objectNames + ); bool success = analyzer.analyze(*_object.code); for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index f60582823..34be474b5 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -278,6 +278,19 @@ BOOST_AUTO_TEST_CASE(args_to_datacopy_are_arbitrary) BOOST_CHECK(successParse(code)); } + +BOOST_AUTO_TEST_CASE(non_existing_objects) +{ + BOOST_CHECK(successParse( + "object \"main\" { code { pop(datasize(\"main\")) } }" + )); + CHECK_ERROR( + "object \"main\" { code { pop(datasize(\"abc\")) } }", + TypeError, + "Unknown data object" + ); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul index b2b01550a..4c1e0feeb 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/object_access.yul @@ -1,15 +1,18 @@ -{ - // Arguments to ``datasize`` and ``dataoffset`` need to be - // literals. We cannot simplify their arguments, but we can - // simplify them as a full expression. - // ``datacopy`` does not have this restriction. - let r := "abc" - let a := datasize("abc") - let x := dataoffset("abc") - // should be replaced by a - let y := datasize("abc") - datacopy("abc", x, y) - mstore(a, x) +object "main" { + code { + // Arguments to ``datasize`` and ``dataoffset`` need to be + // literals. We cannot simplify their arguments, but we can + // simplify them as a full expression. + // ``datacopy`` does not have this restriction. + let r := "abc" + let a := datasize("abc") + let x := dataoffset("abc") + // should be replaced by a + let y := datasize("abc") + datacopy("abc", x, y) + mstore(a, x) + } + data "abc" "Hello, World!" } // ==== // step: commonSubexpressionEliminator diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul b/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul index a7b5e9232..969991871 100644 --- a/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul +++ b/test/libyul/yulOptimizerTests/expressionSplitter/object_access.yul @@ -1,10 +1,13 @@ -{ - // We should never split arguments to ``dataoffset`` - // or ``datasize`` because they need to be literals - let x := dataoffset("abc") - let y := datasize("abc") - // datacopy is fine, though - datacopy(mload(0), mload(1), mload(2)) +object "main" { + code { + // We should never split arguments to ``dataoffset`` + // or ``datasize`` because they need to be literals + let x := dataoffset("abc") + let y := datasize("abc") + // datacopy is fine, though + datacopy(mload(0), mload(1), mload(2)) + } + data "abc" "Hello, World!" } // ==== // step: expressionSplitter From 869d69d293cc07d21fbe011ee69a1e910cd29e78 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 9 Jul 2019 17:23:14 +0200 Subject: [PATCH 2/2] Supply full object to stack compressor and Optimizer Suite. --- libsolidity/codegen/CompilerContext.cpp | 19 +++++++---------- libyul/AsmAnalysis.cpp | 11 ++++++---- libyul/AsmAnalysis.h | 4 +++- libyul/AssemblyStack.cpp | 10 ++------- libyul/CompilabilityChecker.cpp | 20 +++++++++++++----- libyul/CompilabilityChecker.h | 6 +++++- libyul/Object.cpp | 11 ++++++++++ libyul/Object.h | 5 +++++ libyul/backends/wasm/EVMToEWasmTranslator.cpp | 2 +- libyul/optimiser/StackCompressor.cpp | 15 ++++++------- libyul/optimiser/StackCompressor.h | 6 ++++-- libyul/optimiser/Suite.cpp | 21 +++++++++++++------ libyul/optimiser/Suite.h | 7 ++++--- test/libyul/CompilabilityChecker.cpp | 7 ++++--- test/libyul/Parser.cpp | 1 + test/libyul/YulOptimizerTest.cpp | 10 +++++++-- test/tools/yulopti.cpp | 7 ++++++- 17 files changed, 107 insertions(+), 55 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 8c65b8a19..da947073f 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -423,23 +424,19 @@ void CompilerContext::appendInlineAssembly( { bool const isCreation = m_runtimeContext != nullptr; yul::GasMeter meter(dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); + yul::Object obj; + obj.code = parserResult; + obj.analysisInfo = make_shared(analysisInfo); yul::OptimiserSuite::run( dialect, &meter, - *parserResult, - analysisInfo, + obj, _optimiserSettings.optimizeStackAllocation, externallyUsedIdentifiers ); - analysisInfo = yul::AsmAnalysisInfo{}; - if (!yul::AsmAnalyzer( - analysisInfo, - errorReporter, - boost::none, - dialect, - identifierAccess.resolve - ).analyze(*parserResult)) - reportError("Optimizer introduced error into inline assembly."); + analysisInfo = std::move(*obj.analysisInfo); + parserResult = std::move(obj.code); + #ifdef SOL_OUTPUT_ASM cout << "After optimizer: " << endl; cout << yul::AsmPrinter()(*parserResult) << endl; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index abc1f9bee..2622e413a 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -69,17 +70,19 @@ bool AsmAnalyzer::analyze(Block const& _block) return success && !m_errorReporter.hasErrors(); } -AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Block const& _ast) +AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object) { ErrorList errorList; langutil::ErrorReporter errors(errorList); - yul::AsmAnalysisInfo analysisInfo; + AsmAnalysisInfo analysisInfo; bool success = yul::AsmAnalyzer( analysisInfo, errors, Error::Type::SyntaxError, - _dialect - ).analyze(_ast); + _dialect, + {}, + _object.dataNames() + ).analyze(*_object.code); solAssert(success && errorList.empty(), "Invalid assembly/yul code."); return analysisInfo; } diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index b07da7099..facae9187 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -77,7 +77,9 @@ public: bool analyze(Block const& _block); - static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Block const& _ast); + /// Performs analysis on the outermost code of the given object and returns the analysis info. + /// Asserts on failure. + static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object); bool operator()(Instruction const&); bool operator()(Literal const& _literal); diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp index 023048029..15a1267a5 100644 --- a/libyul/AssemblyStack.cpp +++ b/libyul/AssemblyStack.cpp @@ -114,18 +114,13 @@ bool AssemblyStack::analyzeParsed(Object& _object) solAssert(_object.code, ""); _object.analysisInfo = make_shared(); - set objectNames; - objectNames.insert(_object.name); - for (auto const& subObject: _object.subIndexByName) - objectNames.insert(subObject.first); - AsmAnalyzer analyzer( *_object.analysisInfo, m_errorReporter, boost::none, languageToDialect(m_language, m_evmVersion), {}, - objectNames + _object.dataNames() ); bool success = analyzer.analyze(*_object.code); for (auto& subNode: _object.subObjects) @@ -166,8 +161,7 @@ void AssemblyStack::optimize(Object& _object, bool _isCreation) OptimiserSuite::run( dialect, meter.get(), - *_object.code, - *_object.analysisInfo, + _object, m_optimiserSettings.optimizeStackAllocation ); } diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index c25b33c98..7c6fe9d78 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -34,7 +34,7 @@ using namespace dev; map CompilabilityChecker::run( Dialect const& _dialect, - Block const& _ast, + Object const& _object, bool _optimizeStackAllocation ) { @@ -46,16 +46,26 @@ map CompilabilityChecker::run( if (EVMDialect const* evmDialect = dynamic_cast(&_dialect)) { NoOutputEVMDialect noOutputDialect(*evmDialect); - BuiltinContext builtinContext; yul::AsmAnalysisInfo analysisInfo = - yul::AsmAnalyzer::analyzeStrictAssertCorrect(noOutputDialect, _ast); + yul::AsmAnalyzer::analyzeStrictAssertCorrect(noOutputDialect, _object); + BuiltinContext builtinContext; + builtinContext.currentObject = &_object; + for (auto name: _object.dataNames()) + builtinContext.subIDs[name] = 1; NoOutputAssembly assembly; - CodeTransform transform(assembly, analysisInfo, _ast, noOutputDialect, builtinContext, _optimizeStackAllocation); + CodeTransform transform( + assembly, + analysisInfo, + *_object.code, + noOutputDialect, + builtinContext, + _optimizeStackAllocation + ); try { - transform(_ast); + transform(*_object.code); } catch (StackTooDeepError const&) { diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index 63df9bc23..b13d19d88 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -33,15 +34,18 @@ namespace yul * Component that checks whether all variables are reachable on the stack and * returns a mapping from function name to the largest stack difference found * in that function (no entry present if that function is compilable). + * * This only works properly if the outermost block is compilable and * functions are not nested. Otherwise, it might miss reporting some functions. + * + * Only checks the code of the object itself, does not descend into sub-objects. */ class CompilabilityChecker { public: static std::map run( Dialect const& _dialect, - Block const& _ast, + Object const& _object, bool _optimizeStackAllocation ); }; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index a52287934..ea2707c77 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -59,3 +59,14 @@ string Object::toString(bool _yul) const return "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; } + +set Object::dataNames() const +{ + set names; + names.insert(name); + for (auto const& subObject: subIndexByName) + names.insert(subObject.first); + // The empty name is not valid + names.erase(YulString{}); + return names; +} diff --git a/libyul/Object.h b/libyul/Object.h index 8484eb535..5232a3cdf 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -26,6 +26,7 @@ #include #include +#include namespace yul { @@ -63,6 +64,10 @@ public: /// @returns a (parseable) string representation. Includes types if @a _yul is set. std::string toString(bool _yul) const override; + /// @returns the set of names of data objects accessible from within the code of + /// this object. + std::set dataNames() const; + std::shared_ptr code; std::vector> subObjects; std::map subIndexByName; diff --git a/libyul/backends/wasm/EVMToEWasmTranslator.cpp b/libyul/backends/wasm/EVMToEWasmTranslator.cpp index 0f5d7eab1..4df2a0690 100644 --- a/libyul/backends/wasm/EVMToEWasmTranslator.cpp +++ b/libyul/backends/wasm/EVMToEWasmTranslator.cpp @@ -553,7 +553,7 @@ Object EVMToEWasmTranslator::run(Object const& _object) ErrorList errors; ErrorReporter errorReporter(errors); - AsmAnalyzer analyzer(*ret.analysisInfo, errorReporter, boost::none, WasmDialect::instance()); + AsmAnalyzer analyzer(*ret.analysisInfo, errorReporter, boost::none, WasmDialect::instance(), {}, _object.dataNames()); if (!analyzer.analyze(*ret.code)) { // TODO the errors here are "wrong" because they have invalid source references! diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 87492e131..3c417c2dd 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -155,19 +155,20 @@ void eliminateVariables( bool StackCompressor::run( Dialect const& _dialect, - Block& _ast, + Object& _object, bool _optimizeStackAllocation, size_t _maxIterations ) { yulAssert( - _ast.statements.size() > 0 && _ast.statements.at(0).type() == typeid(Block), + _object.code && + _object.code->statements.size() > 0 && _object.code->statements.at(0).type() == typeid(Block), "Need to run the function grouper before the stack compressor." ); - bool allowMSizeOptimzation = !SideEffectsCollector(_dialect, _ast).containsMSize(); + bool allowMSizeOptimzation = !SideEffectsCollector(_dialect, *_object.code).containsMSize(); for (size_t iterations = 0; iterations < _maxIterations; iterations++) { - map stackSurplus = CompilabilityChecker::run(_dialect, _ast, _optimizeStackAllocation); + map stackSurplus = CompilabilityChecker::run(_dialect, _object, _optimizeStackAllocation); if (stackSurplus.empty()) return true; @@ -176,15 +177,15 @@ bool StackCompressor::run( yulAssert(stackSurplus.at({}) > 0, "Invalid surplus value."); eliminateVariables( _dialect, - boost::get(_ast.statements.at(0)), + boost::get(_object.code->statements.at(0)), stackSurplus.at({}), allowMSizeOptimzation ); } - for (size_t i = 1; i < _ast.statements.size(); ++i) + for (size_t i = 1; i < _object.code->statements.size(); ++i) { - FunctionDefinition& fun = boost::get(_ast.statements[i]); + FunctionDefinition& fun = boost::get(_object.code->statements[i]); if (!stackSurplus.count(fun.name)) continue; diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index 604daca96..6504880c4 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -27,13 +27,15 @@ namespace yul { struct Dialect; -struct Block; +struct Object; struct FunctionDefinition; /** * Optimisation stage that aggressively rematerializes certain variables in a function to free * space on the stack until it is compilable. * + * Only runs on the code of the object itself, does not descend into sub-objects. + * * Prerequisite: Disambiguator, Function Grouper */ class StackCompressor @@ -43,7 +45,7 @@ public: /// @returns true if it was successful. static bool run( Dialect const& _dialect, - Block& _ast, + Object& _object, bool _optimizeStackAllocation, size_t _maxIterations ); diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 64cbd4c6d..6c0fb0fbc 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -62,8 +63,7 @@ using namespace yul; void OptimiserSuite::run( Dialect const& _dialect, GasMeter const* _meter, - Block& _ast, - AsmAnalysisInfo const& _analysisInfo, + Object& _object, bool _optimizeStackAllocation, set const& _externallyUsedIdentifiers ) @@ -71,7 +71,12 @@ void OptimiserSuite::run( set reservedIdentifiers = _externallyUsedIdentifiers; reservedIdentifiers += _dialect.fixedFunctionNames(); - Block ast = boost::get(Disambiguator(_dialect, _analysisInfo, reservedIdentifiers)(_ast)); + *_object.code = boost::get(Disambiguator( + _dialect, + *_object.analysisInfo, + reservedIdentifiers + )(*_object.code)); + Block& ast = *_object.code; VarDeclInitializer{}(ast); FunctionHoister{}(ast); @@ -204,7 +209,12 @@ void OptimiserSuite::run( FunctionGrouper{}(ast); // We ignore the return value because we will get a much better error // message once we perform code generation. - StackCompressor::run(_dialect, ast, _optimizeStackAllocation, stackCompressorMaxIterations); + StackCompressor::run( + _dialect, + _object, + _optimizeStackAllocation, + stackCompressorMaxIterations + ); BlockFlattener{}(ast); DeadCodeEliminator{_dialect}(ast); ControlFlowSimplifier{_dialect}(ast); @@ -224,7 +234,6 @@ void OptimiserSuite::run( ast.statements.erase(ast.statements.begin()); } VarNameCleaner{ast, _dialect, reservedIdentifiers}(ast); - yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, ast); - _ast = std::move(ast); + *_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object); } diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 3f35b572a..137066bd9 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -32,9 +32,11 @@ namespace yul struct AsmAnalysisInfo; struct Dialect; class GasMeter; +struct Object; /** - * Optimiser suite that combines all steps and also provides the settings for the heuristics + * Optimiser suite that combines all steps and also provides the settings for the heuristics. + * Only optimizes the code of the provided object, does not descend into the sub-objects. */ class OptimiserSuite { @@ -42,8 +44,7 @@ public: static void run( Dialect const& _dialect, GasMeter const* _meter, - Block& _ast, - AsmAnalysisInfo const& _analysisInfo, + Object& _object, bool _optimizeStackAllocation, std::set const& _externallyUsedIdentifiers = {} ); diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 45188c8c6..5d3181da8 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -37,9 +37,10 @@ namespace { string check(string const& _input) { - shared_ptr ast = yul::test::parse(_input, false).first; - BOOST_REQUIRE(ast); - map functions = CompilabilityChecker::run(EVMDialect::strictAssemblyForEVM(dev::test::Options::get().evmVersion()), *ast, true); + Object obj; + std::tie(obj.code, obj.analysisInfo) = yul::test::parse(_input, false); + BOOST_REQUIRE(obj.code); + map functions = CompilabilityChecker::run(EVMDialect::strictAssemblyForEVM(dev::test::Options::get().evmVersion()), obj, true); string out; for (auto const& function: functions) out += function.first.str() + ": " + to_string(function.second) + " "; diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index fe278c1aa..e747f66bd 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -574,6 +574,7 @@ BOOST_AUTO_TEST_CASE(builtins_analysis) CHECK_ERROR_DIALECT("{ let a, b := builtin(1, 2) }", DeclarationError, "Variable count mismatch: 2 variables and 3 values.", dialect); } + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 2fd9a5ef4..074b9b02a 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -305,7 +305,10 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line disambiguate(); (FunctionGrouper{})(*m_ast); size_t maxIterations = 16; - StackCompressor::run(*m_dialect, *m_ast, true, maxIterations); + Object obj; + obj.code = m_ast; + StackCompressor::run(*m_dialect, obj, true, maxIterations); + m_ast = obj.code; (BlockFlattener{})(*m_ast); } else if (m_optimizerStep == "wordSizeTransform") @@ -318,7 +321,10 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line else if (m_optimizerStep == "fullSuite") { GasMeter meter(dynamic_cast(*m_dialect), false, 200); - OptimiserSuite::run(*m_dialect, &meter, *m_ast, *m_analysisInfo, true); + yul::Object obj; + obj.code = m_ast; + obj.analysisInfo = m_analysisInfo; + OptimiserSuite::run(*m_dialect, &meter, obj, true); } else { diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 58cabd7e3..2729c4577 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -207,8 +208,12 @@ public: SSAReverser::run(*m_ast); break; case 'p': - StackCompressor::run(m_dialect, *m_ast, true, 16); + { + Object obj; + obj.code = m_ast; + StackCompressor::run(m_dialect, obj, true, 16); break; + } default: cout << "Unknown option." << endl; }