-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IR-based compilation w/o optimization uses way too many stack slots, easily hits stack too deep errors #12533
Comments
The IR/Yul code generation from solidity is intentionally "safe and stupid", i.e. it indeed produces a local Yul-variable for each intermediate expression (you quickly see it in compiling the contract with In general, the So this is not exactly unexpected or unintentional, but I agree that it's a bad situation in which the default compiler runs fail even on simple contracts - we should probably enable a minimal set of optimizations by default - however, that's something we'd want to coordinate with you, s.t. we can retain debugging. The currently minimal amount of optimization already makes the contract compilable:
(although right now this will run some hard-coded Yul optimizer steps, we'll allow to disable those in the near future as well #9627) In particular, the Long story short:
|
Would it be an option to disable any code modifications but enable the optimized evm code transforrm? |
@haltman-at @fvictorio With #9627 implemented it's now possible to disable pretty much all optimizations without disabling stack optimization. You can do this by setting Can you check if this would be enough for you to properly support |
I get this error if I do that:
|
Ah, wait. My bad. I was convinced that this feature already went into 0.8.17 but I now realized that we only merged it shortly after the release. Sorry for the confusion. In that case maybe you could try one of the recent builds from our CI? E.g. this one from |
I'm sure optimizerSteps is already there, I've been using "optimizerSteps: '' " for a while. I think he's missing yulDetails in the field chain. |
Yeah, Actually, it could be that clearing the main sequence is already good enough for Hardhat - might be worth a try - but still, it's not clearing the whole sequence. @fvictorio Also, one thing I forgot to mention is that you'll probably want to disable the EVM-based optimizer - clearing the sequence does not automatically do that. You obviously can't just set |
I mentioned this at our meeting in Bogota, but I want to bring it up again: can |
Not sure if But before we do that, I think we should first hear from you whether this mode is actually enough to work around the root issue here. |
I actually misunderstood you in Bogota on this then and thought you wanted something more along the lines of what @cameel proposes, i.e. an independent simple way to enable "only stack-to-memory, no other optimizations". |
We could also introduce explicit optimization levels. Internally |
No misunderstanding, that's what I want. But then it came to my mind that it could be |
I found a very weird bug when using For the record, this does not happen with the nightly version and |
@fvictorio Best to report it - I'd not consider an empty optimizer step sequence common, but it should still work. |
@fvictorio What probably happens is that without optimizer, any mention of a library as an expression (including expressions that will merely result in an internal call) will result in a variable being assigned the address of the library - that variable will be unused and eliminated by the optimizer, but without the optimizer it will remain, so you'll end up with an unresolved link reference, even though it's effectively unused. However, out of my head I'd actually expect this to only happen with |
I reported it here: #13786 |
More information on this: Using a nightly version and Particularly important for us is that the jump types are not as useful with the IR codegen. For example, given this contract: contract C {
uint i = 0;
function test() public {
revert();
i += 1;
}
} If we call the |
This was solved by #13972 . |
Description
Compiling Solidity with
viaIR: true
but the optimizer turned off results in bytecode that uses an enormous number of stack slots and runs into "stack too deep" errors with high frequency, in situations where the Solidity compiler would normally have plenty of stack space left (see repro example below).Basically what's going on here seems to be that, when
viaIR
is set to true, the Solidity compiler generates code that doesn't discard intermediate results after it's done with them. Ordinarily, Solidity divides each stackframe into a lower area for local variables, and a higher area for working state, and the latter only sticks around as necessary. But withviaIR: true
, it's all mixed together, and none of it is discarded promptly.For instance, with the code below (but with the lines about
w
removed so that it actually compiles withviaIR: true
), the lineuint x = 1
, which would normally result in a single 1 being placed on the stack, in the slot representingx
, instead results in two 1s being placed on the stack; presumably, one for the literal and one forx
, and the one for the literal then doesn't go away. All sorts of other intermediate results just remain on the stack as well, even after there's no more need for them, such as the value ofx+y
, the signature ofNum
(multiple times), and the literal88
.And, of course, one result of using so many stack slots and not discarding anything is that it's really to hit stack too deep errors, in situations where the Solidity compiler wouldn't normally be anywhere near such an error.
Thanks!
Environment
Steps to Reproduce
Here's an exampe of a contract that won't compile with
viaIR
on due to stack-too-deep errors:Compiling with
viaIR: true
yields the error message:Meanwhile, with
viaIR: false
, this compiles just fine, because the compiler isn't wasting huge numbers of stack slots.I'll skip including repro steps for the other stuff, but if you just take the above contract and delete the lines mentioning
w
, you'll get the contract I observed them with.The text was updated successfully, but these errors were encountered: