From 8c3c13accdd4b8731d3795e2b151bd35638710fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Fri, 23 Aug 2024 10:44:42 -0300 Subject: [PATCH] Binding rules for inline assembly (#1087) Adds binding rules to support inline Yul assembly --- .../inputs/language/bindings/rules.msgb | 256 ++++++++++++++++++ .../bindings/generated/binding_rules.rs | 256 ++++++++++++++++++ .../src/bindings_assertions/generated/mod.rs | 1 + .../src/bindings_assertions/generated/yul.rs | 40 +++ .../src/bindings_output/generated/mod.rs | 1 + .../src/bindings_output/generated/yul.rs | 25 ++ .../bindings_assertions/yul/blocks.sol | 33 +++ .../bindings_assertions/yul/fun_scopes.sol | 34 +++ .../bindings_assertions/yul/functions.sol | 32 +++ .../bindings_assertions/yul/if_stmt.sol | 19 ++ .../bindings_assertions/yul/labels.sol | 24 ++ .../bindings_assertions/yul/stack_assign.sol | 11 + .../bindings_assertions/yul/variables.sol | 17 ++ .../conditionals/generated/0.4.11-success.txt | 43 +++ .../yul/conditionals/input.sol | 16 ++ .../functions/generated/0.4.11-success.txt | 62 +++++ .../bindings_output/yul/functions/input.sol | 14 + .../yul/loops/generated/0.4.11-success.txt | 51 ++++ .../bindings_output/yul/loops/input.sol | 17 ++ .../variables/generated/0.4.11-success.txt | 21 ++ .../bindings_output/yul/variables/input.sol | 8 + 21 files changed, 981 insertions(+) create mode 100644 crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs create mode 100644 crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/blocks.sol create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/fun_scopes.sol create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/functions.sol create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/if_stmt.sol create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/labels.sol create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/stack_assign.sol create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/variables.sol create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/conditionals/generated/0.4.11-success.txt create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/conditionals/input.sol create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/functions/generated/0.4.11-success.txt create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/functions/input.sol create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/loops/generated/0.4.11-success.txt create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/loops/input.sol create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/variables/generated/0.4.11-success.txt create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/variables/input.sol diff --git a/crates/solidity/inputs/language/bindings/rules.msgb b/crates/solidity/inputs/language/bindings/rules.msgb index 38dfd0bf6..aeea92ddb 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -911,6 +911,11 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @block.lexical_scope -> @stmt.lexical_scope } +;;; Assembly +@stmt [Statement [AssemblyStatement @body body: [YulBlock]]] { + edge @body.lexical_scope -> @stmt.lexical_scope +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; State Variables @@ -1202,3 +1207,254 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @funcall [Expression [FunctionCallExpression @args [ArgumentsDeclaration]]] { edge @args.lexical_scope -> @funcall.lexical_scope } + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Yul +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Blocks and statements + +@block [YulBlock] { + node @block.lexical_scope + ; Variables defined in this block (only used to forward the init block + ; declarations in a for statement) + node @block.variable_defs + ; Function definitions accessible from the block (ie. defined in the block, or + ; accessible in the enclosing parent block) + node @block.function_defs + + edge @block.lexical_scope -> @block.function_defs +} + +@block [YulBlock [YulStatements . @stmt [YulStatement]]] { + edge @stmt.lexical_scope -> @block.lexical_scope +} + +@block [YulBlock [YulStatements @stmt [YulStatement]]] { + edge @stmt.function_scope -> @block.function_defs + edge @block.variable_defs -> @stmt.defs +} + +[YulStatements @left_stmt [YulStatement] . @right_stmt [YulStatement]] { + edge @right_stmt.lexical_scope -> @left_stmt.lexical_scope + ; variable declaration are accessible from the next statement + edge @right_stmt.lexical_scope -> @left_stmt.defs +} + +@stmt [YulStatement] { + node @stmt.lexical_scope + node @stmt.defs + ;; Functions visible in this scope (to propagate to inner function + ;; definitions, since the lexical scope is not accessible inside a function + ;; body) + node @stmt.function_scope +} + +;;; Blocks as statements + +@stmt [YulStatement @block variant: [YulBlock]] { + edge @block.lexical_scope -> @stmt.lexical_scope + edge @block.function_defs -> @stmt.function_scope +} + +;;; Expression as statements + +@stmt [YulStatement @expr_stmt [YulExpression]] { + edge @expr_stmt.lexical_scope -> @stmt.lexical_scope +} + +;;; Variable declarations + +@stmt [YulStatement @var_decl [YulVariableDeclarationStatement]] { + edge @var_decl.lexical_scope -> @stmt.lexical_scope + edge @stmt.defs -> @var_decl.defs +} + +@var_decl [YulVariableDeclarationStatement] { + node @var_decl.lexical_scope + node @var_decl.defs +} + +@var_decl [YulVariableDeclarationStatement [YulVariableNames @name [YulIdentifier]]] { + node def + attr (def) node_definition = @name + attr (def) definiens_node = @var_decl + + edge @var_decl.defs -> def +} + +@var_decl [YulVariableDeclarationStatement [YulVariableDeclarationValue + @value [YulExpression] +]] { + edge @value.lexical_scope -> @var_decl.lexical_scope +} + +;;; Variable assignments + +@stmt [YulStatement @var_assign [YulVariableAssignmentStatement]] { + edge @var_assign.lexical_scope -> @stmt.lexical_scope +} + +@var_assign [YulVariableAssignmentStatement] { + node @var_assign.lexical_scope +} + +@var_assign [YulVariableAssignmentStatement [YulPaths @path [YulPath]]] { + edge @path.lexical_scope -> @var_assign.lexical_scope +} + +@var_assign [YulVariableAssignmentStatement @expr expression: [YulExpression]] { + edge @expr.lexical_scope -> @var_assign.lexical_scope +} + +;;; Function definitions + +@block [YulBlock [YulStatements [YulStatement @fundef [YulFunctionDefinition]]]] { + ;; Function definitions are hoisted in the enclosing block + edge @block.function_defs -> @fundef.def + ;; The only definitions available in the function's lexical scope (other than + ;; parameters) are functions (ie. the body of the function doesn't have access + ;; to any outside variables) + edge @fundef.lexical_scope -> @block.function_defs +} + +@fundef [YulFunctionDefinition + @name name: [YulIdentifier] + @body body: [YulBlock] +] { + node @fundef.lexical_scope + node @fundef.def + + node def + attr (def) node_definition = @name + attr (def) definiens_node = @fundef + + edge @fundef.def -> def + edge @body.lexical_scope -> @fundef.lexical_scope +} + +@fundef [YulFunctionDefinition [YulParametersDeclaration [YulParameters + @param [YulIdentifier] +]]] { + node def + attr (def) node_definition = @param + attr (def) definiens_node = @param + + edge @fundef.lexical_scope -> def +} + +@fundef [YulFunctionDefinition [YulReturnsDeclaration [YulVariableNames + @return_param [YulIdentifier] +]]] { + node def + attr (def) node_definition = @return_param + attr (def) definiens_node = @return_param + + edge @fundef.lexical_scope -> def +} + +;;; Stack assignment (Solidity < 0.5.0) + +@stmt [YulStatement [YulStackAssignmentStatement @name [YulIdentifier]]] { + node ref + attr (ref) node_reference = @name + + edge ref -> @stmt.lexical_scope +} + +;;; If statements + +@stmt [YulStatement [YulIfStatement + @condition condition: [YulExpression] + @body body: [YulBlock] +]] { + edge @condition.lexical_scope -> @stmt.lexical_scope + edge @body.lexical_scope -> @stmt.lexical_scope + edge @body.function_defs -> @stmt.function_scope +} + +;;; Switch statements + +@stmt [YulStatement [YulSwitchStatement + @expr expression: [YulExpression] +]] { + edge @expr.lexical_scope -> @stmt.lexical_scope +} + +@stmt [YulStatement [YulSwitchStatement [YulSwitchCases [YulSwitchCase + [_ @body body: [YulBlock]] +]]]] { + edge @body.lexical_scope -> @stmt.lexical_scope + edge @body.function_defs -> @stmt.function_scope +} + +;;; For statements + +@stmt [YulStatement [YulForStatement + @init initialization: [YulBlock] + @cond condition: [YulExpression] + @iter iterator: [YulBlock] + @body body: [YulBlock] +]] { + edge @init.lexical_scope -> @stmt.lexical_scope + edge @cond.lexical_scope -> @stmt.lexical_scope + edge @iter.lexical_scope -> @stmt.lexical_scope + edge @body.lexical_scope -> @stmt.lexical_scope + + edge @cond.lexical_scope -> @init.variable_defs + edge @iter.lexical_scope -> @init.variable_defs + edge @body.lexical_scope -> @init.variable_defs +} + +;;; Label statements (Solidity < 0.5.0) + +@block [YulBlock [YulStatements [YulStatement @label [YulLabel @name label: [YulIdentifier]]]]] { + node def + attr (def) node_definition = @name + attr (def) definiens_node = @label + + ; Labels are hoisted to the beginning of the block + edge @block.lexical_scope -> def +} + +;;; Expressions + +@expr [YulExpression] { + node @expr.lexical_scope +} + +@expr [YulExpression @path [YulPath]] { + edge @path.lexical_scope -> @expr.lexical_scope +} + +@path [YulPath . [YulPathComponent @name [YulIdentifier]]] { + node @path.lexical_scope + + node ref + attr (ref) node_reference = @name + + edge ref -> @path.lexical_scope +} + +@expr [YulExpression @funcall [YulFunctionCallExpression]] { + edge @funcall.lexical_scope -> @expr.lexical_scope +} + +@funcall [YulFunctionCallExpression + @operand operand: [YulExpression] + @args arguments: [YulArguments] +] { + node @funcall.lexical_scope + + edge @operand.lexical_scope -> @funcall.lexical_scope + edge @args.lexical_scope -> @funcall.lexical_scope +} + +@args [YulArguments] { + node @args.lexical_scope +} + +@args [YulArguments @arg [YulExpression]] { + edge @arg.lexical_scope -> @args.lexical_scope +} diff --git a/crates/solidity/outputs/cargo/slang_solidity/src/generated/bindings/generated/binding_rules.rs b/crates/solidity/outputs/cargo/slang_solidity/src/generated/bindings/generated/binding_rules.rs index 9735349c8..749e9ffbe 100644 --- a/crates/solidity/outputs/cargo/slang_solidity/src/generated/bindings/generated/binding_rules.rs +++ b/crates/solidity/outputs/cargo/slang_solidity/src/generated/bindings/generated/binding_rules.rs @@ -916,6 +916,11 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @block.lexical_scope -> @stmt.lexical_scope } +;;; Assembly +@stmt [Statement [AssemblyStatement @body body: [YulBlock]]] { + edge @body.lexical_scope -> @stmt.lexical_scope +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; State Variables @@ -1208,4 +1213,255 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @args.lexical_scope -> @funcall.lexical_scope } + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Yul +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Blocks and statements + +@block [YulBlock] { + node @block.lexical_scope + ; Variables defined in this block (only used to forward the init block + ; declarations in a for statement) + node @block.variable_defs + ; Function definitions accessible from the block (ie. defined in the block, or + ; accessible in the enclosing parent block) + node @block.function_defs + + edge @block.lexical_scope -> @block.function_defs +} + +@block [YulBlock [YulStatements . @stmt [YulStatement]]] { + edge @stmt.lexical_scope -> @block.lexical_scope +} + +@block [YulBlock [YulStatements @stmt [YulStatement]]] { + edge @stmt.function_scope -> @block.function_defs + edge @block.variable_defs -> @stmt.defs +} + +[YulStatements @left_stmt [YulStatement] . @right_stmt [YulStatement]] { + edge @right_stmt.lexical_scope -> @left_stmt.lexical_scope + ; variable declaration are accessible from the next statement + edge @right_stmt.lexical_scope -> @left_stmt.defs +} + +@stmt [YulStatement] { + node @stmt.lexical_scope + node @stmt.defs + ;; Functions visible in this scope (to propagate to inner function + ;; definitions, since the lexical scope is not accessible inside a function + ;; body) + node @stmt.function_scope +} + +;;; Blocks as statements + +@stmt [YulStatement @block variant: [YulBlock]] { + edge @block.lexical_scope -> @stmt.lexical_scope + edge @block.function_defs -> @stmt.function_scope +} + +;;; Expression as statements + +@stmt [YulStatement @expr_stmt [YulExpression]] { + edge @expr_stmt.lexical_scope -> @stmt.lexical_scope +} + +;;; Variable declarations + +@stmt [YulStatement @var_decl [YulVariableDeclarationStatement]] { + edge @var_decl.lexical_scope -> @stmt.lexical_scope + edge @stmt.defs -> @var_decl.defs +} + +@var_decl [YulVariableDeclarationStatement] { + node @var_decl.lexical_scope + node @var_decl.defs +} + +@var_decl [YulVariableDeclarationStatement [YulVariableNames @name [YulIdentifier]]] { + node def + attr (def) node_definition = @name + attr (def) definiens_node = @var_decl + + edge @var_decl.defs -> def +} + +@var_decl [YulVariableDeclarationStatement [YulVariableDeclarationValue + @value [YulExpression] +]] { + edge @value.lexical_scope -> @var_decl.lexical_scope +} + +;;; Variable assignments + +@stmt [YulStatement @var_assign [YulVariableAssignmentStatement]] { + edge @var_assign.lexical_scope -> @stmt.lexical_scope +} + +@var_assign [YulVariableAssignmentStatement] { + node @var_assign.lexical_scope +} + +@var_assign [YulVariableAssignmentStatement [YulPaths @path [YulPath]]] { + edge @path.lexical_scope -> @var_assign.lexical_scope +} + +@var_assign [YulVariableAssignmentStatement @expr expression: [YulExpression]] { + edge @expr.lexical_scope -> @var_assign.lexical_scope +} + +;;; Function definitions + +@block [YulBlock [YulStatements [YulStatement @fundef [YulFunctionDefinition]]]] { + ;; Function definitions are hoisted in the enclosing block + edge @block.function_defs -> @fundef.def + ;; The only definitions available in the function's lexical scope (other than + ;; parameters) are functions (ie. the body of the function doesn't have access + ;; to any outside variables) + edge @fundef.lexical_scope -> @block.function_defs +} + +@fundef [YulFunctionDefinition + @name name: [YulIdentifier] + @body body: [YulBlock] +] { + node @fundef.lexical_scope + node @fundef.def + + node def + attr (def) node_definition = @name + attr (def) definiens_node = @fundef + + edge @fundef.def -> def + edge @body.lexical_scope -> @fundef.lexical_scope +} + +@fundef [YulFunctionDefinition [YulParametersDeclaration [YulParameters + @param [YulIdentifier] +]]] { + node def + attr (def) node_definition = @param + attr (def) definiens_node = @param + + edge @fundef.lexical_scope -> def +} + +@fundef [YulFunctionDefinition [YulReturnsDeclaration [YulVariableNames + @return_param [YulIdentifier] +]]] { + node def + attr (def) node_definition = @return_param + attr (def) definiens_node = @return_param + + edge @fundef.lexical_scope -> def +} + +;;; Stack assignment (Solidity < 0.5.0) + +@stmt [YulStatement [YulStackAssignmentStatement @name [YulIdentifier]]] { + node ref + attr (ref) node_reference = @name + + edge ref -> @stmt.lexical_scope +} + +;;; If statements + +@stmt [YulStatement [YulIfStatement + @condition condition: [YulExpression] + @body body: [YulBlock] +]] { + edge @condition.lexical_scope -> @stmt.lexical_scope + edge @body.lexical_scope -> @stmt.lexical_scope + edge @body.function_defs -> @stmt.function_scope +} + +;;; Switch statements + +@stmt [YulStatement [YulSwitchStatement + @expr expression: [YulExpression] +]] { + edge @expr.lexical_scope -> @stmt.lexical_scope +} + +@stmt [YulStatement [YulSwitchStatement [YulSwitchCases [YulSwitchCase + [_ @body body: [YulBlock]] +]]]] { + edge @body.lexical_scope -> @stmt.lexical_scope + edge @body.function_defs -> @stmt.function_scope +} + +;;; For statements + +@stmt [YulStatement [YulForStatement + @init initialization: [YulBlock] + @cond condition: [YulExpression] + @iter iterator: [YulBlock] + @body body: [YulBlock] +]] { + edge @init.lexical_scope -> @stmt.lexical_scope + edge @cond.lexical_scope -> @stmt.lexical_scope + edge @iter.lexical_scope -> @stmt.lexical_scope + edge @body.lexical_scope -> @stmt.lexical_scope + + edge @cond.lexical_scope -> @init.variable_defs + edge @iter.lexical_scope -> @init.variable_defs + edge @body.lexical_scope -> @init.variable_defs +} + +;;; Label statements (Solidity < 0.5.0) + +@block [YulBlock [YulStatements [YulStatement @label [YulLabel @name label: [YulIdentifier]]]]] { + node def + attr (def) node_definition = @name + attr (def) definiens_node = @label + + ; Labels are hoisted to the beginning of the block + edge @block.lexical_scope -> def +} + +;;; Expressions + +@expr [YulExpression] { + node @expr.lexical_scope +} + +@expr [YulExpression @path [YulPath]] { + edge @path.lexical_scope -> @expr.lexical_scope +} + +@path [YulPath . [YulPathComponent @name [YulIdentifier]]] { + node @path.lexical_scope + + node ref + attr (ref) node_reference = @name + + edge ref -> @path.lexical_scope +} + +@expr [YulExpression @funcall [YulFunctionCallExpression]] { + edge @funcall.lexical_scope -> @expr.lexical_scope +} + +@funcall [YulFunctionCallExpression + @operand operand: [YulExpression] + @args arguments: [YulArguments] +] { + node @funcall.lexical_scope + + edge @operand.lexical_scope -> @funcall.lexical_scope + edge @args.lexical_scope -> @funcall.lexical_scope +} + +@args [YulArguments] { + node @args.lexical_scope +} + +@args [YulArguments @arg [YulExpression]] { + edge @arg.lexical_scope -> @args.lexical_scope +} + "#####; diff --git a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/mod.rs b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/mod.rs index 67640a3ee..250520054 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/mod.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/mod.rs @@ -14,3 +14,4 @@ mod mappings; mod scoping; mod user_types; mod variables; +mod yul; diff --git a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs new file mode 100644 index 000000000..e324fe909 --- /dev/null +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs @@ -0,0 +1,40 @@ +// This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +use anyhow::Result; + +use crate::bindings_assertions::runner::run; + +#[test] +fn blocks() -> Result<()> { + run("yul", "blocks") +} + +#[test] +fn fun_scopes() -> Result<()> { + run("yul", "fun_scopes") +} + +#[test] +fn functions() -> Result<()> { + run("yul", "functions") +} + +#[test] +fn if_stmt() -> Result<()> { + run("yul", "if_stmt") +} + +#[test] +fn labels() -> Result<()> { + run("yul", "labels") +} + +#[test] +fn stack_assign() -> Result<()> { + run("yul", "stack_assign") +} + +#[test] +fn variables() -> Result<()> { + run("yul", "variables") +} diff --git a/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/mod.rs b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/mod.rs index c52faedd7..aa7ea4bfd 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/mod.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/mod.rs @@ -10,3 +10,4 @@ mod libraries; mod mappings; mod structs; mod variables; +mod yul; diff --git a/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs new file mode 100644 index 000000000..be4e18498 --- /dev/null +++ b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs @@ -0,0 +1,25 @@ +// This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +use anyhow::Result; + +use crate::bindings_output::runner::run; + +#[test] +fn conditionals() -> Result<()> { + run("yul", "conditionals") +} + +#[test] +fn functions() -> Result<()> { + run("yul", "functions") +} + +#[test] +fn loops() -> Result<()> { + run("yul", "loops") +} + +#[test] +fn variables() -> Result<()> { + run("yul", "variables") +} diff --git a/crates/solidity/testing/snapshots/bindings_assertions/yul/blocks.sol b/crates/solidity/testing/snapshots/bindings_assertions/yul/blocks.sol new file mode 100644 index 000000000..e10210b9b --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_assertions/yul/blocks.sol @@ -0,0 +1,33 @@ +contract AssemblyBlocks { + function yul_let(uint256 x) public returns (uint256 z) { + // ^def:2 + // ^def:1 + assembly { + let zero := 0 + // ^def:3 + let v := zero + // ^ref:3 + // ^def:4 + { + z := y + // ^ref:! -- variable is not defined yet + // x { + // ^def:1 + x := add(x_i, outer()) + // ^ref:2 + } + + r := inner(a) + // ^ref:3 + // ^ref:1 + // y { + // ^def:2 + y := inner() + // ^ref:! -- function is not visible here + r := add(a, 1) + // ^ref:! -- assembly functions cannot access Solidity variables + // b { + // ^def:1 + b := add(a, 1) + } + + { + r := add(outer1(x), inner(x)) + // ^ref:2 + // ^ref:1 + function inner(f) -> g { + // ^def:2 + g:= mul(f, outer2(f)) + // ^ref:3 + } + } + + function outer2(c) -> d { + // ^def:3 + d := mul(c, outer2_inner(c)) + // ^ref:4 + + function outer2_inner(e) -> f { + // ^def:4 + f := e + } + } + } + } +} diff --git a/crates/solidity/testing/snapshots/bindings_assertions/yul/if_stmt.sol b/crates/solidity/testing/snapshots/bindings_assertions/yul/if_stmt.sol new file mode 100644 index 000000000..903ffc0dd --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_assertions/yul/if_stmt.sol @@ -0,0 +1,19 @@ +contract Test { + function test() public returns (uint256 r) { + // ^def:1 + uint256 x = 5; + // ^def:2 + assembly { + if gt(x, 2) { + //^ref:2 + r := foo() + // ^ref:3 + // z { + // ^def:3 + z := 1 + } + } + } +} diff --git a/crates/solidity/testing/snapshots/bindings_assertions/yul/labels.sol b/crates/solidity/testing/snapshots/bindings_assertions/yul/labels.sol new file mode 100644 index 000000000..624f29f7f --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_assertions/yul/labels.sol @@ -0,0 +1,24 @@ +contract Test { + function test() public { + // ^def:dummy + assembly { + let n := calldataload(4) + let a := 1 + let b := a + loop: + //= 0.5.0) + a add swap1 + n := sub(n, 1) + jump(loop) + // ^ref:1 (< 0.5.0) + // ^ref:! (>= 0.5.0) + loopend: + // c, d { + │ ──┬─ ┬ ┬ ┬ ┬ + │ ╰───────────────── def: 6 + │ │ │ │ │ + │ ╰────────────── def: 7 + │ │ │ │ + │ ╰─────────── def: 8 + │ │ │ + │ ╰───── def: 9 + │ │ + │ ╰── def: 10 + 9 │ c := b + │ ┬ ┬ + │ ╰─────── ref: 9 + │ │ + │ ╰── ref: 8 + 10 │ d := a + │ ┬ ┬ + │ ╰─────── ref: 10 + │ │ + │ ╰── ref: 7 +────╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/functions/input.sol b/crates/solidity/testing/snapshots/bindings_output/yul/functions/input.sol new file mode 100644 index 000000000..dab773cee --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/functions/input.sol @@ -0,0 +1,14 @@ +contract AssemblyFunctions { + function test(uint256 x) public returns (uint256 r) { + assembly { + let y := add(x, 5) + x, y := swap(x, y) + r := add(x, y) + + function swap(a, b) -> c, d { + c := b + d := a + } + } + } +} diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/loops/generated/0.4.11-success.txt b/crates/solidity/testing/snapshots/bindings_output/yul/loops/generated/0.4.11-success.txt new file mode 100644 index 000000000..49a2c21d2 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/loops/generated/0.4.11-success.txt @@ -0,0 +1,51 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +References and definitions: + ╭─[input.sol:1:1] + │ + 1 │ contract AssemblyLoops { + │ ──────┬────── + │ ╰──────── def: 1 + 2 │ function yul_for_loop() public returns (uint256 z) { + │ ──────┬───── ┬ + │ ╰─────────────────────────────────── def: 2 + │ │ + │ ╰── def: 3 + │ + 4 │ for { let i := 0 } lt(i, 10) { i := add(i, 1) } { z := add(z, 1) } + │ ┬ ┬ ┬ ┬ ┬ ┬ + │ ╰─────────────────────────────────────────────────── def: 4 + │ │ │ │ │ │ + │ ╰─────────────────────────────────────── ref: 4 + │ │ │ │ │ + │ ╰────────────────────────────── ref: 4 + │ │ │ │ + │ ╰───────────────────── ref: 4 + │ │ │ + │ ╰─────────── ref: 3 + │ │ + │ ╰── ref: 3 + │ + 8 │ function yul_while_loop() public returns (uint256 z) { + │ ───────┬────── ┬ + │ ╰──────────────────────────────────── def: 5 + │ │ + │ ╰── def: 6 + │ + 10 │ let i := 0 + │ ┬ + │ ╰── def: 7 + 11 │ for {} lt(i, 5) {} { + │ ┬ + │ ╰── ref: 7 + 12 │ i := add(i, 1) + │ ┬ ┬ + │ ╰─────────── ref: 7 + │ │ + │ ╰── ref: 7 + 13 │ z := add(z, 1) + │ ┬ ┬ + │ ╰─────────── ref: 6 + │ │ + │ ╰── ref: 6 +────╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/loops/input.sol b/crates/solidity/testing/snapshots/bindings_output/yul/loops/input.sol new file mode 100644 index 000000000..7aa60a399 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/loops/input.sol @@ -0,0 +1,17 @@ +contract AssemblyLoops { + function yul_for_loop() public returns (uint256 z) { + assembly { + for { let i := 0 } lt(i, 10) { i := add(i, 1) } { z := add(z, 1) } + } + } + + function yul_while_loop() public returns (uint256 z) { + assembly { + let i := 0 + for {} lt(i, 5) {} { + i := add(i, 1) + z := add(z, 1) + } + } + } +} diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/variables/generated/0.4.11-success.txt b/crates/solidity/testing/snapshots/bindings_output/yul/variables/generated/0.4.11-success.txt new file mode 100644 index 000000000..5b5f23efa --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/variables/generated/0.4.11-success.txt @@ -0,0 +1,21 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +References and definitions: + ╭─[input.sol:1:1] + │ + 1 │ contract AssemblyVariable { + │ ────────┬─────── + │ ╰───────── def: 1 + 2 │ function yul_let() public returns (uint256 z) { + │ ───┬─── ┬ + │ ╰───────────────────────────────── def: 2 + │ │ + │ ╰── def: 3 + │ + 4 │ let x := 123 + │ ┬ + │ ╰── def: 4 + 5 │ z := 456 + │ ┬ + │ ╰── ref: 3 +───╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/variables/input.sol b/crates/solidity/testing/snapshots/bindings_output/yul/variables/input.sol new file mode 100644 index 000000000..1facd41f6 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/variables/input.sol @@ -0,0 +1,8 @@ +contract AssemblyVariable { + function yul_let() public returns (uint256 z) { + assembly { + let x := 123 + z := 456 + } + } +}