mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add verbatim builtin.
This commit is contained in:
@@ -976,6 +976,84 @@ within one Yul subobject. If at least one ``memoryguard`` call is found in a sub
|
||||
the additional optimiser steps will be run on it.
|
||||
|
||||
|
||||
verbatim
|
||||
^^^^^^^^
|
||||
|
||||
The set of ``verbatim...`` builtin functions lets you create bytecode for opcodes
|
||||
that are not known to the Yul compiler. It also allows you to create
|
||||
bytecode sequences that will not be modified by the optimizer.
|
||||
|
||||
The functions are ``verbatim_<n>i_<m>o("<data>", ...)``, where
|
||||
- ``n`` is a decimal between 0 and 99 that specifies the number of input stack slots / variables
|
||||
- ``m`` is a decimal between 0 and 99 that specifies the number of output stack slots / variables
|
||||
- ``data`` is a string literal that contains the sequence of bytes
|
||||
|
||||
If you for example want to define a function that multiplies the input
|
||||
by two, without the optimizer touching the constant two, you can use
|
||||
|
||||
.. code-block:: yul
|
||||
|
||||
let x := calldataload(0)
|
||||
let double := verbatim_1i_1o(hex"600202", x)
|
||||
|
||||
This code will result in a ``dup1`` opcode to retrieve ``x``
|
||||
(the optimizer might directly re-use result of the
|
||||
``calldataload`` opcode, though)
|
||||
directly followed by ``600202``. The code is assumed to
|
||||
consume the copied value of ``x`` and produce the result
|
||||
on the top of the stack. The compiler then generates code
|
||||
to allocate a stack slot for ``double`` and store the result there.
|
||||
|
||||
As with all opcodes, the arguments are arranged on the stack
|
||||
with the leftmost argument on the top, while the return values
|
||||
are assumed to be laid out such that the rightmost variable is
|
||||
at the top of the stack.
|
||||
|
||||
Since ``verbatim`` can be used to generate arbitrary opcodes
|
||||
or even opcodes unknown to the Solidity compiler, care has to be taken
|
||||
when using ``verbatim`` together with the optimizer. Even when the
|
||||
optimizer is switched off, the code generator has to determine
|
||||
the stack layout, which means that e.g. using ``verbatim`` to modify
|
||||
the stack height can lead to undefined behaviour.
|
||||
|
||||
The following is a non-exhaustive list of restrictions on
|
||||
verbatim bytecode that are not checked by
|
||||
the compiler. Violations of these restrictions can result in
|
||||
undefined behaviour.
|
||||
|
||||
- Control-flow should not jump into or out of verbatim blocks,
|
||||
but it can jump within the same verbatim block.
|
||||
- Stack contents apart from the input and output parameters
|
||||
should not be accessed.
|
||||
- The stack height difference should be exactly ``m - n``
|
||||
(output slots minus input slots).
|
||||
- Verbatim bytecode cannot make any assumptions about the
|
||||
surrounding bytecode. All required parameters have to be
|
||||
passed in as stack variables.
|
||||
|
||||
The optimizer does not analyze verbatim bytecode and always
|
||||
assumes that it modifies all aspects of state and thus can only
|
||||
do very few optimizations across ``verbatim`` function calls.
|
||||
|
||||
The optimizer treats verbatim bytecode as an opaque block of code.
|
||||
It will not split it but might move, duplicate
|
||||
or combine it with identical verbatim bytecode blocks.
|
||||
If a verbatim bytecode block is unreachable by the control-flow,
|
||||
it can be removed.
|
||||
|
||||
|
||||
.. warning::
|
||||
|
||||
During discussions about whether or not EVM improvements
|
||||
might break existing smart contracts, features inside ``verbatim``
|
||||
cannot receive the same consideration as those used by the Solidity
|
||||
compiler itself.
|
||||
|
||||
.. note::
|
||||
|
||||
To avoid confusion, all identifiers starting with the string ``verbatim`` are reserved
|
||||
and cannot be used for user-defined identifiers.
|
||||
|
||||
.. _yul-object:
|
||||
|
||||
Specification of Yul Object
|
||||
|
||||
Reference in New Issue
Block a user