-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Description
Abstract
Currently we have a separate verbatim_<n>i_<m>o(c, ...)
builtin for every combination of n
and m
. We should replace it with a single verbatim()
builtin with the first 3 arguments being literal arguments.
Motivation
The current design complicates the implementation, because it has to be treated specially. Internally all other builtins always exist, while verbatim ones are generated on demand. This became problematic especially after #15520, because it makes it harder to give them fixed locations in an array. We rely on the fact that we can't have more than 10000 of them (m
and n
are limited to 99), but the limit is artificial and we're even considering lifting it eventually.
Yul builtins can have literal arguments - arguments that must always be literals, not variables or expressions, so that their values are known at compilation time. Such arguments can be used for m
and n
instead. This seems much simpler both for the implementation and for the user.
Open design questions
- Should we keep the old names reserved or release them?
Specification
- Remove
verbatim_<n>i_<m>o(c, ...)
builtins. - Define the equivalent
verbatim(n, m, c, ...)
builtin:- Mark the first 3 arguments as literal arguments.
- Keep the range restrictions for now.
- Update the docs.
Backwards Compatibility
This is a breaking change for Yul. Solidity and assembly import are unaffected, because verbatim
is not available in inline assembly.
Due to not being available in inline assembly verbatim()
does not seem widely used. We decided it does not need a deprecation period. We'll swap one version for another in a breaking release.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Activity
[-]Replace `verbatim_<n>i_<m>o(c)` builtins with a single `verbatim(i, o, c)`[/-][+]Convert `verbatim` into a single builtin with literal arguments[/+]cameel commentedon Mar 10, 2025
Well, it turns out that the reason is pretty obvious. Each builtin has a different number of arguments and outputs. The only alternative would be something with variadic args and we don't have that in Yul.
Only seeing this from the C++ implementation side and looking at the generated assembly I somehow missed the fact that in Yul you can't just put the inputs on the stack directly and they must be passed in via arguments. I should have realized this earlier, but TBH when I asked why it is the way it is no one else seemed to be able to explain it either.
In any case, we won't be able to do it the way I proposed here so I'm closing the issue. Unfortunately this still leaves us with a somewhat problematic mechanism for generating these builtins dynamically.
cameel commentedon Mar 10, 2025
After discussing with @ekpyron, it's actually still viable. Since the values of literal arguments are known ahead of time, we can make the function signature depend on them.
Having the literal args mixed in with normal ones makes it feel like a more dynamic mechanism, but we could get their values even during parsing if needed, so it really won't be that much different from extracting the numbers of inputs and outputs out of the function name.
IMO we should also consider introducing some special syntax for literal arguments.