One way to ease the verification issue is to introduce a stack counter variable (sc), and the following opcodes:
ADD_SC16 ADD_SC32 ADD_SC64 ADD_SC128
which will accumulate sc variable with the corresponding value.
When calling the existing DUPx/SWAPx , x in 1…16, opcodes, it will actually do DUPx/SWAPx with the stack variable at position x + sc. After calling DUPx/SWAPx, sc will be reset to 0.
For the record, I’d love to see this picked up again and be considered for inclusion for the initial EOF version :-). For us in Solidity, resp. actually for Yul, this would simplify things a lot and make it much easier to generate simpler and more optimal code. If there’s interest and it helps, I could look into producing some stats about this, let me know.
That’s actually a pretty nice proposal. Originally the idea was that one could just keep using SWAPN/DUPN` only, but since it has immediates, they are fixed just like the existing ones. I think it would make sense following your suggestion.
For the record (we also discussed this offline): We could work with it either way, but starting from 17 for the immediate argument opcodes and thus avoiding to have multiple opcodes with the same behaviour, also seems reasonable to me.
Probably more useful than SWAP_N would be SWAP_N_M, which takes two immediates and swaps the n’th and m’th stack items. This is important for stack scheduling as right now swapping the nth and mth items takes three instructions.
IMO there is no problem with having redundant instructions. Starting from 17 (i.e., SWAP_N 1 actually meaning SWAP17) would be a source of confusion and footguns, forever. The fact that the SWAP and DUP instructions were originally designed without immediates should not lead to a confusing design for the new instructions. Having the redundant instructions also provides a forward path for phasing out the old instructions, if that becomes attractive in the future.
Since most of us weren’t too decided (mostly just slightly in favour) about this and there was already a more concerned voice before yours, I think we are leaning towards not taking the +17 offset.
The rationale read like:
The offset 17 was chosen to avoid these new instructions overlapping with the existing DUP? and SWAP? instructions, which are cheaper to deploy because they take a single byte. Having the overlap provides little benefit, and likely would see very little use.
We did consider “deprecating” the old opcodes, but that could realistically only happen within EOF, and it felt like a harsh change due to the increased code size limit it would cause.
Well, I did not really mean that the old opcodes should be deprecated immediately. But at some point code size constraints may be less important. In any case, in the meantime, I don’t see the conceptual complexity that will stem from N starting from 17 to justify having an extra 16 possible addressable items.