Commit Graph
13 Commits
Author SHA1 Message Date
LJandxermicus a4163512ff Improve compilation time in standard JSON mode and honor requested output (#461)
# Description

Compilation times for resolc were significantly slower than solc when:
* Multiple files were included in the JSON input file via
`--standard-json`
* And none of the files requested code generation
* (If only a subset of files requested code generation, both resolc and
solc were very slow)

Reason:
* Resolc unconditionally generated bytecode for all contracts, even if
not requested.
* When compiling to PolkaVM bytecode, we need to pass additional flags
(e.g. `irOptimized`) to solc. If these flags were not explicitly
requested, resolc also added these to the requested output since PolkaVM
bytecode was always generated.

## Breaking Changes

The following changes are breaking, but fix the semantics to match its
intended behavior:

* Compiling with `--standard-json` now compiles to PolkaVM bytecode
***only*** for the contracts explicitly requested in the
`outputSelection`.
* Compiling with `--standard-json` now outputs ***only*** the explicitly
requested output (e.g. `evm.assembly`, `evm.bytecode`, `ast`, etc.).

```jsonc
// Example:
{
  "settings": {
    // ...
    "outputSelection": {
      "src/common/GasService.sol": {
        // Contracts in this file will generate bytecode.
        // Only these fields of the JSON output selection will be in the `contracts` output.
        "*": ["abi", "evm.methodIdentifiers", "metadata", "evm.bytecode"],
        // Only this field of the JSON output selection will be in the `sources` output.
        "": ["ast"]
      },
      "src/common/Gateway.sol": {
        // No contracts in this file will generate bytecode.
        "*": ["abi", "evm.methodIdentifiers", "metadata"],
        // No `ast` will be in the `sources` output (only the automatically added `id`,
        // similar to solc as this is not a configurable output selection).
        "": []
      },
    }
  }
}
```

## Performance Improvements

When e.g. the standard JSON input file includes multiple files and
requests output for every contract as per this setting:

```jsonc
{
  "settings": {
    // ...
    "optimizer": { "enabled": true, "runs": 1 },
    "viaIR": true,
    "outputSelection": {
      "src/common/GasService.sol": {
        "*": ["abi", "evm.methodIdentifiers", "metadata", "evm.bytecode"],
      },
      // Rest of files..
    }
  }
}
```

The differences in compilation times depending on whether `evm.bytecode`
is selected in every file, one file, or no files can be seen below:

| Solc Optimizer (runs=1) | ViaIR | Request `abi`,
`evm.methodIdentifiers`, `metadata` | Request `evm.bytecode` | resolc
before | resolc after | solc v0.8.33 |

|:-----------------------:|:-----:|:---------:|:---------:|:-------------:|:------------:|:----------:|
| ✅ | ✅ | All files | All files | `~14.5s` | `~14.5s` | `~13.5s` |
| ✅ | ✅ | All files | One file | `~14.5s` | `~450ms` | `~13.5s` |
| ✅ | ✅ | All files | No files | `~14.5s` | `~390ms` | `~350ms` |

**Observations:**

* `resolc before` is roughly the same no matter the request
  * This is due to unconditionally generating bytecode
* When not requesting bytecode for any contracts:
  * `resolc after` now compiles in ~390ms (vs ~14.5s), similar to `solc`
* Neither `solc` nor `resolc after` generates bytecode when none of the
contracts request it
* When requesting bytecode for all contracts in _only one_ file:
  * `resolc after` now compiles in ~450ms (vs ~14.5s)
* `solc` still compiles in the same time as when requesting bytecode for
all contracts in all files
* This is something they have tried to improve (see
[Solidity#15373](https://github.com/argotorg/solidity/issues/15373) and
[Solidity#15615](https://github.com/argotorg/solidity/issues/15615)),
and the intended behavior seems to now be that bytecode should only be
generated when explicitly requested for each contract.
* Even though PRs have merged to try to fix it, their issue seems to
persist as of v0.8.33.

# Open Questions

* Foundry:
  * [x] Pruning of the AST:
* Just saw [this past
commit](https://github.com/paritytech/revive/pull/385) to not prune the
AST for Foundry compatibility.
    * Can Foundry not explicitly request `"": "ast"`?
    * **Answer:**
* Pruning the AST when not requested should be fine, as long as Foundry
explicitly requests it when needed.
      * Will be tested by Foundry maintainer.

# Review Notes

Changes in `docs/` (~25 files) can be skipped as they are automatically
updated after adding content to `book/` and rebuilding it.

# Resolved Issues

Closes #326

---------

Co-authored-by: xermicus <cyrill@parity.io>
2026-01-28 23:04:22 +01:00
LJ c601377c2d Add integration test for deleting struct (#459)
Differentially tests the behavior of deleting a struct with a member
that do not occupy the full 32-byte slot. From [this
issue](https://github.com/paritytech/contract-issues/issues/118) it was
unclear whether the `delete` was expected to reset only the bytes
occupied or the entire slot. The current behavior of resetting the
entire slot is expected.
2026-01-20 14:34:27 +01:00
LJ 7cc001ddf4 Update rendering of resolc binaries Markdown tables (#454)
Fixes the rendering of the Markdown tables for `resolc-bin` which do not
render inside the `details` tags for GH pages. Removes `details` and
instead adds a table of contents at the top for fast navigation to
respective platform.
2026-01-15 13:37:02 +01:00
LJ 2d85ca9755 ci: Add build tool to workflow (#453)
Fixes
[this](https://github.com/paritytech/revive/actions/runs/21000852574/job/60370115169)
and
[this](https://github.com/paritytech/revive/actions/runs/21008888013/job/60398447550)
failed runs.
2026-01-15 09:26:40 +01:00
LJ f5fe3faa71 Add default values to compiler arguments (#451)
## Description

Adds default values to the compiler arguments below when parsed by
`clap`. This does not change previous user-facing behavior as these
defaults were implemented using different logic, but improves the UX and
the visibility of the exact defaults used.

**Example output from `resolc --help`:**
(Only affected arguments are shown here, and some of their descriptions
have been omitted here.)
```
Options:

  -O, --optimization <OPTIMIZATION>
          Set the optimization parameter -O[0 | 1 | 2 | 3 | s | z]. Use `3` for best performance and `z` for minimal size
          
          [default: z]

      --metadata-hash <METADATA_HASH>
          Set the metadata hash type. Available types: `none`, `ipfs`, `keccak256`
          
          [default: keccak256]

      --heap-size <HEAP_SIZE>
          The emulated EVM linear heap memory static buffer size in bytes.
          ...
          
          [default: 131072]

      --stack-size <STACK_SIZE>
          The contracts total stack size in bytes.
          ...
          
          [default: 131072]
```

## Resolved Issues

Closes #446
2026-01-14 19:22:03 +01:00
LJ 3bcb62ac0b ci: Add GHA workflow executing benchmarks (#422)
## Description

Adds a workflow executing the resolc and yul benchmarks.

* The workflow can be manually triggered via the Actions UI.
* User input:
  * Branch, tag, or SHA before changes (e.g. `main`) _(required)_
* Branch, tag, or SHA after changes (e.g. `lj/ci-benchmarks`)
_(required)_
  * PR number  _(optional)_
* If provided, the benchmarking result will be posted as a PR comment
      * The comment is updated if it exists, otherwise it is created
    * If omitted, the result is uploaded as an artifact

This PR originally implemented the workflow to automatically run on each
PR once its tests passed successfully. As we likely do not need to run
this workflow for each PR, the workflow has been rewritten to manually
trigger it.

Providing user input also allows for comparisons between any commits,
such as releases.

## Notes

### File must exist on the default branch

* This workflow is triggered by a `workflow_dispatch` event
[only](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#workflow_dispatch)
if the workflow file exists on the default branch. **Therefore, the
workflow cannot be run for this PR.** (See section below on how it has
still been tested.)
* Once merged, for any subsequent PRs that modify this workflow, those
changes will be testable before merge (by choosing to run the workflow
from the PR branch).

## Testing the Workflow

I've tested a similar enough workflow in a personal repo in order to
push it to `main` and trigger it. Will verify again once this PR is
merged.

- [x] Runs when provided with branch names
- [x] Runs when provided with SHAs
- [x] A PR comment is created if a PR number is provided and the comment
does not exist
- [x] A PR comment is updated if a PR number is provided and the comment
already exists
- [x] An artifact is created if a PR number is omitted
- [x] An in-progress run is cancelled if another one is triggered
comparing the same refs

## Example PR Comment

<details>
    <summary>Expand to see an example PR comment</summary>

# Benchmarks

* **Ref Before:** `main`
* **Ref After:** `lj/ci-benchmarks`

## Compile E2E

<details>
    <summary>Results</summary>

```
group                                            resolc_before                            resolc_changes
-----                                            -------------                            --------------
Dependency/resolc                                1.00    144.0±6.94ms        ? ?/sec      1.00    144.6±5.97ms        ? ?/sec
Dependency/solc                                  1.04    65.9±10.73ms        ? ?/sec      1.00    63.5±10.10ms        ? ?/sec
Empty/resolc                                     1.03     68.8±4.40ms        ? ?/sec      1.00     66.6±4.61ms        ? ?/sec
Empty/solc                                       1.13     11.2±2.01ms        ? ?/sec      1.00     10.0±2.28ms        ? ?/sec
LargeDivRem/resolc                               1.00    119.3±5.62ms        ? ?/sec      1.02   121.3±17.03ms        ? ?/sec
LargeDivRem/solc                                 1.15     24.7±3.15ms        ? ?/sec      1.00     21.5±1.03ms        ? ?/sec
Memset (`--yul`)/resolc                          1.02     62.7±3.92ms        ? ?/sec      1.00     61.7±3.76ms        ? ?/sec
Memset (`--yul`)/solc                            1.00      9.0±0.84ms        ? ?/sec      1.12     10.1±2.23ms        ? ?/sec
Multiple Contracts (`--standard-json`)/resolc    1.01  1559.2±68.95ms        ? ?/sec      1.00  1539.3±64.92ms        ? ?/sec
Multiple Contracts (`--standard-json`)/solc      1.01   652.0±19.38ms        ? ?/sec      1.00   648.4±31.83ms        ? ?/sec
Return (`--yul`)/resolc                          1.00    60.1±17.02ms        ? ?/sec      1.02    61.2±14.50ms        ? ?/sec
Return (`--yul`)/solc                            1.09      8.8±2.37ms        ? ?/sec      1.00      8.0±3.08ms        ? ?/sec
```

</details>

## Parse Yul

<details>
    <summary>Results</summary>

```
group             yul_parse_before                         yul_parse_changes
-----             ----------------                         -----------------
Baseline/parse    1.07      8.9±3.64µs        ? ?/sec      1.00      8.4±0.09µs        ? ?/sec
ERC20/parse       1.00   162.5±34.25µs        ? ?/sec      1.07  173.3±123.25µs        ? ?/sec
SHA1/parse        1.01    80.8±33.04µs        ? ?/sec      1.00    80.3±52.82µs        ? ?/sec
Storage/parse     1.00     16.9±8.15µs        ? ?/sec      1.01     17.2±7.54µs        ? ?/sec
Transfer/parse    1.00     18.5±0.23µs        ? ?/sec      1.23    22.7±18.50µs        ? ?/sec
```

</details>

## Lower Yul

<details>
    <summary>Results</summary>

```
group             yul_lower_before                         yul_lower_changes
-----             ----------------                         -----------------
Baseline/lower    1.00    122.1±5.95µs        ? ?/sec      1.09   133.6±35.12µs        ? ?/sec
ERC20/lower       1.00   641.7±13.24µs        ? ?/sec      1.15  735.6±665.92µs        ? ?/sec
SHA1/lower        1.00   361.4±78.47µs        ? ?/sec      1.09  392.3±114.48µs        ? ?/sec
Storage/lower     1.00   167.2±50.34µs        ? ?/sec      1.01   168.2±32.45µs        ? ?/sec
Transfer/lower    1.00    167.5±8.70µs        ? ?/sec      1.03   173.1±16.32µs        ? ?/sec
```

</details>

</details>

## Resolved Issues

Closes #405
2026-01-14 17:00:55 +01:00
LJandxermicus 55c4e32b82 Show binary releases details on resolc-bin GH Pages site (#447)
## Description

For more easily finding the details of the resolc binary releases for
the various supported platforms, the plain JSON information will be
displayed on [resolc-bin](https://github.com/paritytech/resolc-bin)'s
[GitHub Pages website](https://paritytech.github.io/resolc-bin/).

Changes:
* Whenever there is a regular or nightly release:
* The corresponding workflow files will run a script to update
resolc-bin's `index.md` file (new file) with the updated JSON.
* `index.md` will be the file GitHub Pages serves as HTML (by default it
is built with Jekyll and the Markdown is processed by kramdown, hence
the syntax seen in the script).
* Documentation  updates

Thus, this will run on the next nightly release after this PR is merged.

## Resolved Issues

Closes #443

---------

Co-authored-by: xermicus <cyrill@parity.io>
2026-01-12 18:32:40 +01:00
LJ 94b14b079b ci: Bump macos runner images (#417)
Closes #416.

Workflows using x86_64-apple-darwin target with a `macos-13` runner
image have been migrated to `macos-15-intel` due to deprecation (see
#416), and `macos-14` images have been migrated to `macos-15`.
2025-11-29 11:06:30 +01:00
LJandxermicus 0742227c5a Implement Yul to LLVM IR compilation benchmarks (#407)
# Description

Closes [#404](https://github.com/paritytech/revive/issues/404)

Adds compilation time benchmarks for:

* Parsing of Yul source code -> AST Object
* Lowering of AST Object -> LLVM IR (unoptimized)

The benchmarks can be run from the root via:

```sh
# Run all benchmarks in the revive-yul crate (parsing + lowering)
make bench-yul
```

HTML reports will be generated under `target/criterion`, and a summary
of the results at
[crates/yul/BENCHMARKS_PARSE_M4PRO.md](https://github.com/paritytech/revive/blob/lj/compilation-benchmarks-yul/crates/yul/BENCHMARKS_PARSE_M4PRO.md)
and
[crates/yul/BENCHMARKS_LOWER_M4PRO.md](https://github.com/paritytech/revive/blob/lj/compilation-benchmarks-yul/crates/yul/BENCHMARKS_LOWER_M4PRO.md)
(currently from running on a Mac M4 Pro).

---------

Co-authored-by: xermicus <cyrill@parity.io>
2025-11-25 12:00:06 +01:00
LJ ad61b6e3c9 Implement resolc end-to-end compilation benchmarks (#406)
# Description

Closes [#403](https://github.com/paritytech/revive/issues/403)

Adds compilation time benchmarks for resolc end-to-end.

The benchmarks can be run from the root via:

```sh
make bench-resolc
```

HTML reports will be generated under `target/criterion`, and a summary
of the results at
[crates/resolc/BENCHMARKS_M4PRO.md](https://github.com/paritytech/revive/blob/lj/compilation-benchmarks/crates/resolc/BENCHMARKS_M4PRO.md)
(currently from running on a Mac M4 Pro).
2025-11-19 12:16:07 +01:00
LJ 2f89c743ce Implement Rust CLI tests (#372)
# Description

Closes #365 

Ports all `resolc` CLI tests to Rust and removes the CLI TypeScript
tests.
2025-08-19 16:04:05 +02:00
LJandxermicus ea0ea711ad Update workflows to skip tests for only .md files (#371)
When updating documentation Markdown files, long-running tests still run
unnecessarily. With these changes, it will skip running test workflows
when PRs only containing changes to such files are opened.

Co-authored-by: xermicus <cyrill@parity.io>
2025-08-12 16:12:14 +02:00
LJ b31e8a0d74 Fix llvm-builder installation docs (#370)
Updated installation instructions for the llvm-builder.
2025-08-11 21:48:40 +02:00