Skip to content

Conversation

ironcev
Copy link
Member

@ironcev ironcev commented Sep 14, 2025

Description

This PR implements the compilation of the ABI backtracking, as described in the ABI Backtracking RFC.

The PR closes two remaining implementation steps listed in the #7276:

  • Compile runtime backtracing to ASM and compile-time to ABI JSON
  • Support backtracing in forc test

Changes in the ABI JSON and IR Compilation

panickingCalls section in the ABI JSON

Each panicking call is identified by a unique number and provided in the new panickingCalls section in the ABI JSON.

E.g., for this panicking call in a module some_module of a package some_package:

fn some_function() {
    let _ = this_function_might_panic(42);
}

the following ABI JSON entry is created:

"panickingCalls": {
    "1": {
        "pos": {
            "function": "some_package::some_module::some_function",
            "pkg": "some_package@0.1.0",
            "file": "src/some_module.sw",
            "line": 4,
            "column": 8
        },
        "function": "some_other_package::module::this_function_might_panic"
    },
}

Encoding error code and backtrace in a panic revert code

The generation of the panic revert code is changed. A panic revert code now encodes:

  • the information that the revert is generated by a panic expression,
  • the actual error code that can be located in the errorCodes section of the ABI JSON,
  • up to five panicking call IDs, encoded in the order of calling, that can be located in the panickingCalls section of the ABI JSON.

The encoding of the u64 revert code works as following:

1_pppppppp_CCCCCCCCCCC_CCCCCCCCCCC_CCCCCCCCCCC_CCCCCCCCCCC_CCCCCCCCCCC
  • The leading 1 denotes a revert code generated by a panic expression. Arbitrary user-defined revert codes will must have the starting bit set to 0 or in other words be less then or equal to 9223372036854775807₁₀ = 7FFFFFFFFFFFFFFF₁₆.
  • The pppppppp denotes the error code in the errorCodes section of the ABI JSON, that identifies the actual panic location.
  • Each CCCCCCCCCCC section denotes a panicking call code in the panickingCalls section of the ABI JSON. The calls represent the callstack, where the right-most code is the code of the immediate function call in which the panic occurs. If all Cs a zero it means no-call. This will happen if the actual call-depth is less then five calls.

Calculating backtrace

Ever non-entry function that can panic gets an additional function argument: __backtrace: u64. The __backtrace to pass to a panicking call is calculated at runtime by left-shift the existing __backtrace provided by the caller function and append/bitwise OR the unique panicking call ID of the exact panicking call. The ID of that exact panicking call is a compile-time, compiler-generated constant as explained above.

The detailed mechanism with examples is provided in the "Runtime execution and bytecode and gas overhead" chapter of the ABI Backtracking RFC.

Additional Changes

The panickingCalls section of the ABI JSON can differ between debug and release builds which required adding support for different ABI JSON oracle files in test that validate_abi. The requirement to display a fully qualified function name in the panicking call and the backtrace resulted in adding flexibility to displaying functions and types in general. Adjusting affected tests was used as opportunity to remove unnecessary dependencies to the std and reduced std libraries in a large number of tests. Also, a cleanup is done in some parts of the code, like, e.g., removing code duplications.

The PR implements these additional changes:

  • Implementing TyFunctionDisplay and TypeInfoDisplay for configurable displaying of functions and types. Replacing current various custom implementations of displaying with these two types, mostly in error messages, will be done in separate PRs, with low priority. Also, display might be improved in some edge cases. There are TODOs left in code for such, and improvements will be done in separate PRs, with lower priority.
  • Displaying full type names in warnings and errors, where expected. The PR intentionally temporarily switches to full type names in all errors and warnings by making that a default behavior in impl DisplayWithEngines for TypeInfo. This is done so that we can easily spot errors and warnings that should use specific TyFunctionDisplay and TypeInfoDisplay (tests will break) and adapt those in the follow up PR that will address Add settings to TypeInfoDisplay for optimal displaying of types in different contexts #7389.
  • Implementing expressive diagnostics for CompileError::MethodNotFound and utilize TyFunctionDisplay for displaying all matching candidates.
  • Implementing Value::new_u64_constant and removing duplicated code for a common scenario of creating an IR Constant of type u64.
  • Removing several unnecessary clone()s and String allocations.
  • Renaming fields postfixed with typeid to follow more general naming convention for TypeId fields and parameters.
  • Removing unnecessary dependencies to std or reduced std libraries in tests.
  • Adding support for different json_abi_oracle files for debug and release build profiles. The panickingCalls part of the ABI JSON can vary depending on the build profile. A test that verifies ABI JSON now must provide expected oracles for both build profiles, unless a profile is unsupported via unsupported_profiles test option. An alternative was considered, to allow just a single oracle file if both debug and release oracles are the same. The reasoning for having two as mandatory even in that case was to gain more explicit test setup. We can change this upon feedback if needed. The oracles have a suffix of either .debug.json or .release.json and the name part is, as before, one of the following:
    • json_abi_oracle for obsolete old encoding,
    • json_abi_oracle.<experimental feature> for experimental features,
    • json_abi_oracle_new_encoding for new encoding without other experimental features.
  • Fixing One error code in ABI for panics in functions of same name and content #7386.
  • Fixing Invalid ABI auto impl name if the package name contains hypens #7388.

Checklist

  • I have linked to any relevant issues.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have updated the documentation where relevant (API docs, the reference, and the Sway book).
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added (or requested a maintainer to add) the necessary Breaking* or New Feature labels where relevant.
  • I have done my best to ensure that my PR adheres to the Fuel Labs Code Review Standards.
  • I have requested a review from the relevant team or maintainers.

@ironcev ironcev self-assigned this Sep 14, 2025
@ironcev ironcev added compiler General compiler. Should eventually become more specific as the issue is triaged compiler: ir IRgen and sway-ir including optimization passes ABI Everything to do the ABI, especially the JSON representation compiler: frontend Everything to do with type checking, control flow analysis, and everything between parsing and IRgen labels Sep 14, 2025
Copy link

codspeed-hq bot commented Sep 14, 2025

CodSpeed Performance Report

Merging #7387 will degrade performances by 11.31%

Comparing ironcev/abi-backtracing-compile-backtracing (d206565) with master (79f7c60)

Summary

❌ 1 regression
✅ 24 untouched

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark BASE HEAD Change
open_all_example_workspace_members 9.9 s 11.2 s -11.31%

@ironcev
Copy link
Member Author

ironcev commented Sep 14, 2025

The CI will be failing until we close the necessary circular dependency with fuels-rs. This will be done after the fuels-rs feat/abi-backtracing branch is integrated and a temporary release is published.

Aside from that, the PR is ready for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ABI Everything to do the ABI, especially the JSON representation compiler: frontend Everything to do with type checking, control flow analysis, and everything between parsing and IRgen compiler: ir IRgen and sway-ir including optimization passes compiler General compiler. Should eventually become more specific as the issue is triaged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant