Skip to content

feat(slang): inline assembly - #671

Open
abinavpp wants to merge 3 commits into
main-slangfrom
app-slang-inline-assembly
Open

feat(slang): inline assembly#671
abinavpp wants to merge 3 commits into
main-slangfrom
app-slang-inline-assembly

Conversation

@abinavpp

@abinavpp abinavpp commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Lowers assembly { .. } in the Slang frontend to a sol.inline_asm region of Yul-dialect ops, mirroring the C++ frontend: every inline-assembly-legal Yul builtin, Yul functions, control flow, and Solidity local/state/calldata references through the sol.yul_* bridge ops. Yul call arguments are evaluated right to left as the spec requires, which the C++ frontend does not yet do.

cargo run-tester-slang: 5476 -> 11580 passed, 4 -> 6 failed, 1740 -> 1607 invalid (both new failures explained in the thread).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Slang-frontend support for Solidity inline assembly { ... } by lowering it into a sol.inline_asm region containing Yul-dialect MLIR ops, plus the required Yul IR wrappers/bridge ops in solx-mlir and lit coverage to validate parity (and the intended arg-evaluation order differences vs solc).

Changes:

  • Implement inline-assembly lowering in solx-slang with an AssemblyScope that tracks Yul variables/functions and leave return slots.
  • Introduce Yul dialect IR wrappers (Word, Slot, YulBlock, YulFunction, predicates, references) and Sol↔Yul bridge ops/macros in solx-mlir.
  • Add lit tests covering Yul builtins, declarations, control flow, scoping, external references, and evaluation order.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated no comments.

Show a summary per file
File Description
solx-slang/src/scope/mod.rs Adds assembly scope module export and updates scope docs.
solx-slang/src/scope/assembly.rs Introduces AssemblyScope to manage Yul bindings and region emission.
solx-slang/src/contract/function/statement/mod.rs Routes AssemblyStatement lowering instead of unimplemented!().
solx-slang/src/contract/function/mod.rs Exposes new inline-assembly lowering module.
solx-slang/src/contract/function/assembly/mod.rs Lowers assembly {} to sol.inline_asm, declares/defines Yul functions.
solx-slang/src/contract/function/assembly/statement.rs Lowers Yul statements and control-flow constructs.
solx-slang/src/contract/function/assembly/reference.rs Resolves Yul paths to Yul vars or bridged Solidity refs (sol.yul_*).
solx-slang/src/contract/function/assembly/expression.rs Lowers Yul expressions and builtin/Yul-function calls (RTL arg eval).
solx-mlir/tests/lit/assembly.sol Lit coverage for a broad set of Yul builtins + memory-safe attribute.
solx-mlir/tests/lit/assembly_function_scopes.sol Tests sibling function-name reuse + leave in for-init behavior (solx-only).
solx-mlir/tests/lit/assembly_external_references.sol Tests bridging of locals/state vars/storage/calldata/function ptrs/constants.
solx-mlir/tests/lit/assembly_evaluation_order.sol Asserts solx vs solc arg evaluation order differences.
solx-mlir/tests/lit/assembly_declarations.sol Tests let defaults/materialization ordering and tuple assignment.
solx-mlir/tests/lit/assembly_control_flow.sol Tests Yul if/for/switch/break/continue/functions/forward refs.
solx-mlir/src/macros.rs Generalizes op-wrapper macro to dialect_ops! and adds Yul kinds/support.
solx-mlir/src/lib.rs Exports Yul IR wrapper types publicly.
solx-mlir/src/ir/yul/word.rs Adds Word wrapper for Yul i256 SSA values.
solx-mlir/src/ir/yul/slot.rs Adds Slot wrapper for !yul.ptr.
solx-mlir/src/ir/yul/reference.rs Adds YulReference abstraction (slot vs compile-time word).
solx-mlir/src/ir/yul/predicate.rs Defines YulCmpPredicate attribute enum for yul.cmp.
solx-mlir/src/ir/yul/mod.rs Declares Yul op-wrapper surface via dialect_ops! (builtins, load/store, calls).
solx-mlir/src/ir/yul/function.rs Adds YulFunction emitter for yul.func and entry block creation.
solx-mlir/src/ir/yul/block.rs Adds YulBlock helpers for Yul control-flow ops and terminators.
solx-mlir/src/ir/type/mod.rs Introduces Type::yul_word and Type::yul_pointer.
solx-mlir/src/ir/mod.rs Adds sol.inline_asm builder + Sol↔Yul bridge ops (sol.yul_*).
solx-mlir/src/ir/attributes.rs Renames predicate macro usage to shared predicate_attribute!.
solx-mlir/src/ffi.rs Adds FFI for constructing !yul.ptr type.
solx-mlir/sol_attr_stubs.cpp Implements solxCreateYulPtrType via Yul dialect C++ API.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

Coverage Summary

Crate Line Coverage Function Coverage
solx 🟢 83.6% 🔴 20.0%
solx-benchmark-converter 🔴 0.0% 🔴 0.0%
solx-codegen-evm 🔴 25.5% 🔴 13.5%
solx-compiler-downloader 🔴 0.0% 🔴 0.0%
solx-core 🔴 38.6% 🔴 47.4%
solx-dev 🔴 2.4% 🔴 3.0%
solx-evm-assembly 🔴 0.0% 🔴 0.0%
solx-mlir 🔴 49.4% 🔴 44.0%
solx-slang 🔴 20.1% 🔴 28.7%
solx-solc-test-adapter 🔴 1.7% 🔴 2.1%
solx-standard-json 🔴 42.8% 🔴 47.7%
solx-tester 🔴 36.5% 🔴 34.3%
solx-utils 🔴 29.3% 🔴 32.9%
solx-yul 🔴 0.0% 🔴 0.0%
Total 🔴 10.9% 🔴 13.1%

Codecov Report | HTML Report | Workflow Run

@abinavpp
abinavpp force-pushed the app-slang-inline-assembly branch 2 times, most recently from ae099d0 to 3be1889 Compare August 20, 2026 18:29
Yul evaluates an argument list in the order the EVM pushes it, so a call whose arguments have side effects runs the rightmost one first.
Same-named Yul functions in sibling blocks land in the one sol.inline_asm symbol table, so the symbol needs node-id disambiguation; separately, a `leave` in a for-initializer terminates the block, which left the loop op appended after a terminator.
@abinavpp
abinavpp force-pushed the app-slang-inline-assembly branch from ad292a3 to 053c48c Compare August 21, 2026 08:32
@abinavpp
abinavpp requested a lite review from Copilot August 21, 2026 11:28
@abinavpp
abinavpp marked this pull request as ready for review August 21, 2026 11:28
@abinavpp
abinavpp requested a review from hedgar2017 August 21, 2026 11:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated no new comments.

Suppressed comments (2)

solx-slang/src/contract/function/assembly/expression.rs:67

  • yul_call builds an intermediate expressions Vec just to reverse-iterate it. You can iterate node.arguments() in reverse directly to avoid the extra allocation and traversal while keeping the required right-to-left evaluation order.
        let expressions: Vec<_> = node.arguments().iter().collect();
        let mut arguments: Vec<_> = expressions
            .iter()
            .rev()
            .map(|argument| self.yul_expression(argument))
            .collect();
        arguments.reverse();

solx-slang/src/contract/function/assembly/reference.rs:87

  • This clones the state-variable symbol name on every reference (.name.clone()). Since the value is only needed as &str for building the IR op, you can borrow it directly and avoid the allocation.
                    .storage_layout
                    .get(&state_variable.node_id())
                    .expect("state variable is registered in the storage layout")
                    .name
                    .clone();

@abinavpp

Copy link
Copy Markdown
Contributor Author

cargo run-tester-slang, origin/main-slang (6387d7e) vs this branch, same slot, both at the pinned solx-llvm/solx-solidity:

main-slang this PR
passed 5472 11576
failed 8 10
invalid 1740 1607

The two new failures are yul_instructions/calldatasize's one_deploy and zero_deploy, INVALID on the base (the file did not compile) and now failing on main.sol:19, which hardcodes 132 bytes of Deploy creation code - this branch emits 144, so at len 0 and 1 the CREATE gets truncated init code. The other cases of that file copy enough and pass.

The remaining 8 failures are identical on both sides: 4 function_modifier.sol cases (no modifiers in solx yet) and 4 standard_functions_high_order.sol cases.

cargo test-slang 201 passed, lit 133/133.

@abinavpp

Copy link
Copy Markdown
Contributor Author

@hedgar2017 the two new failures in the tally above are yul_instructions/calldatasize's zero_deploy and one_deploy. The file was INVALID before this PR - nothing here supported inline assembly - so this is the first time it has run.

main.sol hardcodes Deploy's creation-code length (add(132, len)); this branch emits 144 bytes, so those two cases copy truncated init code and the CREATE reverts. Taking the real length fixes them, with a clamp because the largest case would otherwise cross the EIP-3860 init-code limit:

let size := add(mload(deploy_calldata), len)
if gt(size, 49152) { size := 49152 }
let result := create(0, add(deploy_calldata, 32), size)

With that, every case in the file passes locally. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants