All About the Via-Ir Pipeline
This post explains what the via-ir pipeline is and how it works. It also discusses some of the most common challenges when parsing the via-ir-compiled contracts.
What is via-ir
?
The via-ir
flag, if set to true
, enables the Yul
intermediary language in the compilation pipeline. This means that your Solidity code will be first compiled into the Yul IR. After this intermediary compilation, the Yul optimizer repeatedly applies optimizations to the Yul code, before advancing to the EVM assembly step.
In the EVM Assembly step, the Yul code is transformed into EVM assembly, which is very close to the actual bytecode, but is still suitable for further optimizations.
The steps would look something like this:
To get a better understanding of via-ir
, you can take a look at this talk by Nikola from Solidity
The tooling problems of via-ir
The new IR pipeline is pretty good at applying optimizations, especially for local variables, almost completely eliminating stack too deep
errors. In many cases, it also creates code that is more gas-optimized than the direct pipeline, making it an appealing option.
But currently, there are major problems with the IR pipeline, stopping it from being default:
- First of all, the debugging symbols and source mappings can’t be preserved easily due to the increased number of optimization steps.
- Also, a big obstacle is the format used for the debugging data. Currently, Solidity provides information in the AST and source maps, which can hold only some of the data needed to write a quality debugger. This format forces all tooling providers to rely on heuristics and educated guesses to interpret the executed instructions.
- Since the Yul optimizer can do much better optimizations than the original optimizer, it makes 100% mapping impossible. Parsing local calls is the main problem here. The optimizer can easily inline code, add tail-call optimizations, or do any other optimization that changes the stack placement of function arguments. These optimizations are impossible to identify without the help of the optimizer, leaving room for errors in argument parsing.
- There is a similar problem with local variables. The optimizer can shuffle and reorder local variables as needed. This allows the compiler to remove the
stack too deep
errors but makes the variables impossible to track.
Conclusion
With these problems that the compiler has in the via-ir
pipeline, it’s impossible to provide 100% accurate data when dealing with local function calls or local variables. This is why Evaluate Expression cannot provide accurate information in these cases. For this reason, Evaluate Expression is disabled for IR-compiled contracts until compiler support is provided.
The Solidity team is aware of these problems, which is why the IR pipeline isn’t a default option. However, an initiative to actively create a debugging data format for EVM languages is ongoing. Once the format is complete and the Solidity compiler can output it, Debugger and Evaluate Expression will undergo major improvements.
You can take a look at this talk by G.Nick about the debug initiative.