feat(slang): inline assembly - #671
Conversation
There was a problem hiding this comment.
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-slangwith anAssemblyScopethat tracks Yul variables/functions andleavereturn slots. - Introduce Yul dialect IR wrappers (
Word,Slot,YulBlock,YulFunction, predicates, references) and Sol↔Yul bridge ops/macros insolx-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.
Coverage Summary
|
ae099d0 to
3be1889
Compare
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.
ad292a3 to
053c48c
Compare
There was a problem hiding this comment.
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_callbuilds an intermediateexpressionsVec just to reverse-iterate it. You can iteratenode.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&strfor 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();
|
The two new failures are The remaining 8 failures are identical on both sides: 4
|
|
@hedgar2017 the two new failures in the tally above are
With that, every case in the file passes locally. What do you think? |
Lowers
assembly { .. }in the Slang frontend to asol.inline_asmregion 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 thesol.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).