| 237 | } |
| 238 | |
| 239 | std::tuple<bool, Block> StackCompressor::run( |
| 240 | Object const& _object, |
| 241 | bool _optimizeStackAllocation, |
| 242 | size_t _maxIterations) |
| 243 | { |
| 244 | yulAssert(_object.hasCode()); |
| 245 | yulAssert(_object.dialect(), "No dialect"); |
| 246 | yulAssert( |
| 247 | !_object.code()->root().statements.empty() && std::holds_alternative<Block>(_object.code()->root().statements.at(0)), |
| 248 | "Need to run the function grouper before the stack compressor." |
| 249 | ); |
| 250 | bool usesOptimizedCodeGenerator = false; |
| 251 | auto evmDialect = dynamic_cast<EVMDialect const*>(_object.dialect()); |
| 252 | if (evmDialect) |
| 253 | { |
| 254 | yulAssert(!evmDialect->eofVersion().has_value(), "StackCompressor does not support EOF."); |
| 255 | usesOptimizedCodeGenerator = |
| 256 | _optimizeStackAllocation && |
| 257 | evmDialect->evmVersion().canOverchargeGasForCall() && |
| 258 | evmDialect->providesObjectAccess(); |
| 259 | } |
| 260 | bool allowMSizeOptimization = !MSizeFinder::containsMSize(*_object.dialect(), _object.code()->root()); |
| 261 | Block astRoot = std::get<Block>(ASTCopier{}(_object.code()->root())); |
| 262 | if (usesOptimizedCodeGenerator) |
| 263 | { |
| 264 | yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( |
| 265 | *_object.dialect(), |
| 266 | astRoot, |
| 267 | _object.summarizeStructure() |
| 268 | ); |
| 269 | std::unique_ptr<CFG> cfg = ControlFlowGraphBuilder::build(analysisInfo, *_object.dialect(), astRoot); |
| 270 | yulAssert(evmDialect); |
| 271 | eliminateVariablesOptimizedCodegen( |
| 272 | *_object.dialect(), |
| 273 | astRoot, |
| 274 | StackLayoutGenerator::reportStackTooDeep(*cfg, *evmDialect), |
| 275 | allowMSizeOptimization |
| 276 | ); |
| 277 | } |
| 278 | else |
| 279 | { |
| 280 | for (size_t iterations = 0; iterations < _maxIterations; iterations++) |
| 281 | { |
| 282 | Object object(_object); |
| 283 | object.setCode(std::make_shared<AST>(*_object.dialect(), std::get<Block>(ASTCopier{}(astRoot)))); |
| 284 | std::map<YulName, int> stackSurplus = CompilabilityChecker(object, _optimizeStackAllocation).stackDeficit; |
| 285 | if (stackSurplus.empty()) |
| 286 | return std::make_tuple(true, std::move(astRoot)); |
| 287 | eliminateVariables( |
| 288 | *object.dialect(), |
| 289 | astRoot, |
| 290 | stackSurplus, |
| 291 | allowMSizeOptimization |
| 292 | ); |
| 293 | } |
| 294 | } |
| 295 | return std::make_tuple(false, std::move(astRoot)); |
| 296 | } |
nothing calls this directly
no test coverage detected