Skip to content

ICE user-defined Yul function named _ collides with internal functions #475

@elle-j

Description

@elle-j

Description

An Internal Compiler Error (ICE) occurs when compiling valid Yul code that defines a function named _ (in --yul mode) or _ or $_ (in --standard-json mode). This is valid Yul, but our naming convention causes a collision with built-in functions.

The internal function name for a user-defined function _ becomes __deploy or __runtime (depending on code context), which collides with the internal function names:

/// The deploy code function name.
pub const FUNCTION_DEPLOY_CODE: &str = "__deploy";
/// The runtime code function name.
pub const FUNCTION_RUNTIME_CODE: &str = "__runtime";

Note

Related (but different) issue: #474

Detected when trying (using --standard-json mode) to compile resolc-compiler-tests/fixtures/yul/semantic/function_definitions.yul which uses $_ as a function name. Similar to the related issue, the path taken in standard JSON mode goes via solc to get the optimized IR. Solc renames $_ to _, which then causes a collision in resolc.

Minimal Reproduction Using --yul and Function Name _

1. Create a Yul file that triggers the ICE

cat > ice-name-conflict-with-internal.yul << 'EOF'
object "Test" {
    code {
        {
            let size := datasize("Test_deployed")
            codecopy(0, dataoffset("Test_deployed"), size)
            return(0, size)
        }
    }
    object "Test_deployed" {
        code {
            {
                _()
                return(0, 32)
            }
            function _()
            {
                mstore(0, 0xdeadbeef)
            }
        }
    }
}
EOF

2. Compile the file with resolc

RUST_BACKTRACE=1 resolc --yul ice-name-conflict-with-internal.yul --bin

3. For comparison, compile the file with solc

solc --strict-assembly ice-name-conflict-with-internal.yul --bin

Expected Outcome

The compiler should output PVM bytecode. A function named _ is a valid Yul identifier.

Actual Outcome

solc outputs EVM bytecode.

resolc panics with an ICE:

Error: "/path/to/bin/resolc" subprocess failed with exit code Some(101):


thread '<unnamed>' (37758766) panicked at crates/llvm-context/src/polkavm/context/mod.rs:459:9:
ICE: function '_' declared subsequentally
stack backtrace:
   0: __rustc::rust_begin_unwind
   1: core::panicking::panic_fmt
   2: revive_llvm_context::polkavm::context::Context::add_function
   3: <revive_yul::parser::statement::function_definition::FunctionDefinition as revive_llvm_context::polkavm::WriteLLVM>::declare
   4: <revive_yul::parser::statement::block::Block as revive_llvm_context::polkavm::WriteLLVM>::into_llvm
   5: <revive_yul::parser::statement::block::Block as revive_llvm_context::polkavm::WriteLLVM>::into_llvm
   6: <revive_llvm_context::polkavm::context::function::runtime::runtime_code::RuntimeCode<B> as revive_llvm_context::polkavm::WriteLLVM>::into_llvm
   7: <revive_yul::parser::statement::object::Object as revive_llvm_context::polkavm::WriteLLVM>::into_llvm
   8: <revive_yul::parser::statement::object::Object as revive_llvm_context::polkavm::WriteLLVM>::into_llvm
   9: resolc::project::contract::Contract::compile
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

thread 'main' (37758752) panicked at crates/resolc/src/process/native_process.rs:51:14:
Threading error: Any { .. }
--> ice-name-conflict-with-internal.yul:Test

Minimal Reproduction Using --standard-json and Function Name $_

1. Create the standard JSON input file that triggers the ICE

cat > ice-name-conflict-with-internal-2.yul << 'EOF'
object "Test" {
    code {
        {
            let size := datasize("Test_deployed")
            codecopy(0, dataoffset("Test_deployed"), size)
            return(0, size)
        }
    }
    object "Test_deployed" {
        code {
            {
                $_()
                return(0, 32)
            }
            function $_()
            {
                mstore(0, 0xdeadbeef)
            }
        }
    }
}
EOF

In the JSON, make sure optimizer.enabled is false to prevent solc from inlining this simple function (which would prevent detecting the bug/ICE):

cat > ice-name-conflict-with-internal-2.json << EOF
{
  "language": "Yul",
  "sources": {
    "ice-name-conflict-with-internal-2.yul": {
      "content": $(cat ice-name-conflict-with-internal-2.yul | jq -Rs .)
    }
  },
  "settings": {
    "optimizer": {
      "enabled": false
    },
    "outputSelection": {
      "*": {
        "*": ["evm.bytecode"]
      }
    }
  }
}
EOF

2. Compile the file with resolc

RUST_BACKTRACE=1 resolc --standard-json < ice-name-conflict-with-internal-2.json | jq

Expected Outcome

The compiler should output PVM bytecode. A function named $_ is a valid Yul identifier.

Actual Outcome

{
  "errors": [
    {
      "component": "general",
      "errorCode": null,
      "formattedMessage": "Error: \"/path/to/bin/resolc\" subprocess failed with exit code Some(101):\n\n\nthread '<unnamed>' (37978903) panicked at crates/llvm-context/src/polkavm/context/mod.rs:459:9:\nICE: function '_' declared subsequentally\nstack backtrace:\n   0: __rustc::rust_begin_unwind\n   1: core::panicking::panic_fmt\n   2: revive_llvm_context::polkavm::context::Context::add_function\n   3: <revive_yul::parser::statement::function_definition::FunctionDefinition as revive_llvm_context::polkavm::WriteLLVM>::declare\n   4: <revive_yul::parser::statement::block::Block as revive_llvm_context::polkavm::WriteLLVM>::into_llvm\n   5: <revive_llvm_context::polkavm::context::function::runtime::runtime_code::RuntimeCode<B> as revive_llvm_context::polkavm::WriteLLVM>::into_llvm\n   6: <revive_yul::parser::statement::object::Object as revive_llvm_context::polkavm::WriteLLVM>::into_llvm\n   7: <revive_yul::parser::statement::object::Object as revive_llvm_context::polkavm::WriteLLVM>::into_llvm\n   8: resolc::project::contract::Contract::compile\nnote: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n\nthread 'main' (37978889) panicked at crates/resolc/src/process/native_process.rs:51:14:\nThreading error: Any { .. }\nstack backtrace:\n   0: __rustc::rust_begin_unwind\n   1: core::panicking::panic_fmt\n   2: core::result::unwrap_failed\n   3: <resolc::process::native_process::NativeProcess as resolc::process::Process>::run\n   4: resolc::main_inner\n   5: resolc::main\nnote: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n--> ice-name-conflict-with-internal-2.yul:Test\n\n",
      "message": "\"/path/to/bin/resolc\" subprocess failed with exit code Some(101):\n\n\nthread '<unnamed>' (37978903) panicked at crates/llvm-context/src/polkavm/context/mod.rs:459:9:\nICE: function '_' declared subsequentally\nstack backtrace:\n   0: __rustc::rust_begin_unwind\n   1: core::panicking::panic_fmt\n   2: revive_llvm_context::polkavm::context::Context::add_function\n   3: <revive_yul::parser::statement::function_definition::FunctionDefinition as revive_llvm_context::polkavm::WriteLLVM>::declare\n   4: <revive_yul::parser::statement::block::Block as revive_llvm_context::polkavm::WriteLLVM>::into_llvm\n   5: <revive_llvm_context::polkavm::context::function::runtime::runtime_code::RuntimeCode<B> as revive_llvm_context::polkavm::WriteLLVM>::into_llvm\n   6: <revive_yul::parser::statement::object::Object as revive_llvm_context::polkavm::WriteLLVM>::into_llvm\n   7: <revive_yul::parser::statement::object::Object as revive_llvm_context::polkavm::WriteLLVM>::into_llvm\n   8: resolc::project::contract::Contract::compile\nnote: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n\nthread 'main' (37978889) panicked at crates/resolc/src/process/native_process.rs:51:14:\nThreading error: Any { .. }\nstack backtrace:\n   0: __rustc::rust_begin_unwind\n   1: core::panicking::panic_fmt\n   2: core::result::unwrap_failed\n   3: <resolc::process::native_process::NativeProcess as resolc::process::Process>::run\n   4: resolc::main_inner\n   5: resolc::main\nnote: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n",
      "severity": "error",
      "sourceLocation": {
        "file": "ice-name-conflict-with-internal-2.yul:Test",
        "start": -1,
        "end": -1
      },
      "type": "Error"
    }
  ],
  "version": "0.8.33",
  "long_version": "0.8.33+commit.64118f21.Darwin.appleclang"
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions