You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/ir-breaking-changes.rst
+44-10Lines changed: 44 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,17 +5,40 @@
5
5
Solidity IR-based Codegen Changes
6
6
*********************************
7
7
8
-
This section highlights the main differences between the old and the IR-based codegen,
9
-
along with the reasoning behind the changes and how to update affected code.
8
+
Solidity can generate EVM bytecode in two different ways:
9
+
Either directly from Solidity to EVM opcodes ("old codegen") or through
10
+
an intermediate representation ("IR") in Yul ("new codegen" or "IR-based codegen").
11
+
12
+
The IR-based code generator was introduced with an aim to not only allow
13
+
code generation to be more transparent and auditable but also
14
+
to enable more powerful optimization passes that span across functions.
15
+
16
+
Currently, the IR-based code generator is still marked experimental,
17
+
but it supports all language features and has received a lot of testing,
18
+
so we consider it almost ready for production use.
19
+
20
+
You can enable it on the command line using ``--experimental-via-ir``
21
+
or with the option ``{"viaIR": true}`` in standard-json and we
22
+
encourage everyone to try it out!
23
+
24
+
For several reasons, there are tiny semantic differences between the old
25
+
and the IR-based code generator, mostly in areas where we would not
26
+
expect people to rely on this behaviour anyway.
27
+
This section highlights the main differences between the old and the IR-based codegen.
10
28
11
29
Semantic Only Changes
12
30
=====================
13
31
14
32
This section lists the changes that are semantic-only, thus potentially
15
33
hiding new and different behavior in existing code.
16
34
17
-
- When storage structs are deleted, every storage slot that contains a member of the struct is set to zero entirely. Formally, padding space was left untouched.
18
-
Consequently, if the padding space within a struct is used to store data (e.g. in the context of a contract upgrade), you have to be aware that ``delete`` will now also clear the added member (while it wouldn't have been cleared in the past).
35
+
- When storage structs are deleted, every storage slot that contains
36
+
a member of the struct is set to zero entirely. Formerly, padding space
37
+
was left untouched.
38
+
Consequently, if the padding space within a struct is used to store data
39
+
(e.g. in the context of a contract upgrade), you have to be aware that
40
+
``delete`` will now also clear the added member (while it wouldn't
41
+
have been cleared in the past).
19
42
20
43
.. code-block:: solidity
21
44
@@ -132,7 +155,10 @@ This causes differences in some contracts, for example:
132
155
Previously, ``y`` would be set to 0. This is due to the fact that we would first initialize state variables: First, ``x`` is set to 0, and when initializing ``y``, ``f()`` would return 0 causing ``y`` to be 0 as well.
133
156
With the new rules, ``y`` will be set to 42. We first initialize ``x`` to 0, then call A's constructor which sets ``x`` to 42. Finally, when initializing ``y``, ``f()`` returns 42 causing ``y`` to be 42.
134
157
135
-
- Copying ``bytes`` arrays from memory to storage is implemented in a different way. The old code generator always copies full words, while the new one cuts the byte array after its end. The old behaviour can lead to dirty data being copied after the end of the array (but still in the same storage slot).
158
+
- Copying ``bytes`` arrays from memory to storage is implemented in a different way.
159
+
The old code generator always copies full words, while the new one cuts the byte
160
+
array after its end. The old behaviour can lead to dirty data being copied after
161
+
the end of the array (but still in the same storage slot).
136
162
This causes differences in some contracts, for example:
137
163
138
164
.. code-block:: solidity
@@ -155,8 +181,10 @@ This causes differences in some contracts, for example:
155
181
}
156
182
}
157
183
158
-
Previously ``f()`` would return ``0x6465616462656566313564656164000000000000000000000000000000000010`` (it has correct length, and correct first 8 elements, but then it contains dirty data which was set via assembly).
159
-
Now it is returning ``0x6465616462656566000000000000000000000000000000000000000000000010`` (it has correct length, and correct elements, but does not contain superfluous data).
184
+
Previously ``f()`` would return ``0x6465616462656566313564656164000000000000000000000000000000000010``
185
+
(it has correct length, and correct first 8 elements, but then it contains dirty data which was set via assembly).
186
+
Now it is returning ``0x6465616462656566000000000000000000000000000000000000000000000010`` (it has
187
+
correct length, and correct elements, but does not contain superfluous data).
160
188
161
189
.. index:: ! evaluation order; expression
162
190
@@ -183,7 +211,8 @@ This causes differences in some contracts, for example:
183
211
184
212
.. index:: ! evaluation order; function arguments
185
213
186
-
On the other hand, function argument expressions are evaluated in the same order by both code generators with the exception of the global functions ``addmod`` and ``mulmod``.
214
+
On the other hand, function argument expressions are evaluated in the same order
215
+
by both code generators with the exception of the global functions ``addmod`` and ``mulmod``.
187
216
For example:
188
217
189
218
.. code-block:: solidity
@@ -227,11 +256,15 @@ This causes differences in some contracts, for example:
227
256
- Old code generator: ``aMod = 0`` and ``mMod = 2``
228
257
- New code generator: ``aMod = 4`` and ``mMod = 0``
229
258
230
-
- The new code generator imposes a hard limit of ``type(uint64).max`` (``0xffffffffffffffff``) for the free memory pointer. Allocations that would increase its value beyond this limit revert. The old code generator does not have this limit.
259
+
- The new code generator imposes a hard limit of ``type(uint64).max``
260
+
(``0xffffffffffffffff``) for the free memory pointer. Allocations that would
261
+
increase its value beyond this limit revert. The old code generator does not
262
+
have this limit.
231
263
232
264
For example:
233
265
234
266
.. code-block:: solidity
267
+
:force:
235
268
236
269
// SPDX-License-Identifier: GPL-3.0
237
270
pragma solidity >0.8.0;
@@ -264,7 +297,7 @@ The old code generator uses code offsets or tags for values of internal function
264
297
these offsets are different at construction time and after deployment and the values can cross this border via storage.
265
298
Because of that, both offsets are encoded at construction time into the same value (into different bytes).
266
299
267
-
In the new code generator, function pointers use the AST IDs of the functions as values. Since calls via jumps are not possible,
300
+
In the new code generator, function pointers use internal IDs that are allocated in sequence. Since calls via jumps are not possible,
268
301
calls through function pointers always have to use an internal dispatch function that uses the ``switch`` statement to select
269
302
the right function.
270
303
@@ -280,6 +313,7 @@ Cleanup
280
313
281
314
The old code generator only performs cleanup before an operation whose result could be affected by the values of the dirty bits.
282
315
The new code generator performs cleanup after any operation that can result in dirty bits.
316
+
The hope is that the optimizer will be powerful enough to eliminate redundant cleanup operations.
0 commit comments