Skip to content

docs: improved documentation of evaluation order differences #16143

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

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions docs/ir-breaking-changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ hiding new and different behavior in existing code.

The arguments to the global functions ``addmod`` and ``mulmod`` are evaluated right-to-left by the old code generator
and left-to-right by the new code generator.

This difference occurs because of how the two code generators handle argument evaluation:

- In the legacy code generator (``ExpressionCompiler.cpp``), ``addmod`` and ``mulmod`` arguments are explicitly processed in reverse order (right-to-left) in the ``FunctionType::Kind::AddMod`` and ``FunctionType::Kind::MulMod`` cases.
- In the IR-based code generator (``IRGeneratorForStatements.cpp``), arguments are processed in source order (left-to-right) following the general expression evaluation pattern.

For example:

.. code-block:: solidity
Expand All @@ -226,6 +232,29 @@ hiding new and different behavior in existing code.
- Old code generator: ``aMod = 0`` and ``mMod = 2``
- New code generator: ``aMod = 4`` and ``mMod = 0``

.. note::
To write code that behaves consistently between both code generators, avoid expressions with side effects (like increment operators) in ``addmod`` and ``mulmod`` arguments. Instead, evaluate the arguments separately before calling the function:

.. code-block:: solidity

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.1;
contract C {
function f() public pure returns (uint256 aMod, uint256 mMod) {
uint256 x = 3;
uint256 a = ++x;
uint256 b = ++x;
uint256 c = x;
aMod = addmod(a, b, c);

uint256 y = x;
uint256 d = ++y;
uint256 e = ++y;
uint256 f = y;
mMod = mulmod(d, e, f);
}
}

- 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
Expand Down