argotorg / argotorg/solidity

Legacy vs IR codegen disagree on evaluation order [INFORMATIONAL]

Open
#16,802 3 comments 0 reactions 0 assignees View on GitHub
low impact
Dominant language
C++
Stars
25.7k
Forks
6.2k
Avg merge
1d 11h
Merged PRs (30d)
21

Description

## Description

Legacy and IR (`--via-ir`) codegen disagree on the **order of evaluation** of a binary operator's left operand relative to a side-effecting assignment in its right operand. The same contract, same calldata, returns different values depending on the codegen pipeline.

A nested assignment inside the divisor of a `/` mutates the variable that is also the dividend. The IR pipeline reads the dividend *before* the nested assignment executes; the legacy pipeline reads it *after*. The two pipelines therefore return different results.

## Minimal reproducer

```solidity
contract C {
function test() public payable returns (uint256) {
uint p0;
assembly { p0 := calldataload(0) }
return (p0 = p0 / ((p0 = p0 / (p0 | 1)) | 1));
}
}
```

Call `test()` so that `calldataload(0)` (which reads the calldata starting at the selector) yields a large non-zero value `V`. Concretely, calling the selector `f8a8fd6d` followed by `0b` gives `p0 = V = 0xf8a8fd6d0b000…000`.

## Observed behavior

| Pipeline | Return value |
| --- | --- |
| `--via-ir` (opt and no-opt) | `0xf8a8fd6d0b00000000000000000000000000000000000000000000000000000000` |
| `--via-ir --via-ssa-cfg` | `0xf8a8fd6d0b00000000000000000000000000000000000000000000000000000000` |
| legacy (opt and no-opt) | `0x0000000000000000000000000000000000000000000000000000000000000000` |

Both legacy configs agree with each other, and all three IR configs agree with each other, but the two families disagree.

## Order of evaluation is unspecified, as per docs, so this is not a BUG per se

Per the docs the [order of evaluation of expressions is unspecified](https://docs.soliditylang.org/en/latest/control-structures.html#order-of-evaluation-of-expressions), so neither result is strictly wrong.

## Version

```
0.8.36-develop / commit 090bc8ff
```

Found via differential fuzzing (legacy vs via-ir).

Contributor guide

Open the contributing guide

Research direction

Start by compiling the minimal Solidity contract with the listed legacy, --via-ir, and --via-ir --via-ssa-cfg configurations, then call test() with the provided calldata and compare the results. Read the expression order documentation before assessing whether the differing outputs require compiler alignment, a regression test, or documentation; the issue does not define a specific desired change.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, solidity
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.