From 143751d0ff4d839cc589f71f63fb53484f584ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Tue, 20 Aug 2024 17:57:19 -0400 Subject: [PATCH 1/8] Binding rules for Yul statements and var declaration and assignments --- .../inputs/language/bindings/rules.msgb | 103 ++++++++++++++++++ .../bindings/generated/binding_rules.rs | 103 ++++++++++++++++++ .../src/bindings_assertions/generated/mod.rs | 1 + .../src/bindings_assertions/generated/yul.rs | 10 ++ .../src/bindings_output/generated/mod.rs | 1 + .../src/bindings_output/generated/yul.rs | 10 ++ .../bindings_assertions/yul/variables.sol | 14 +++ .../variables/generated/0.4.11-success.txt | 21 ++++ .../bindings_output/yul/variables/input.sol | 8 ++ 9 files changed, 271 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/variables.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 aa558ea91..3f4355a09 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -803,6 +803,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 @@ -1060,3 +1065,101 @@ 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 + node @block.defs +} + +@block [YulBlock [YulStatements . @stmt [YulStatement]]] { + edge @stmt.lexical_scope -> @block.lexical_scope +} + +[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 +} + +;;; Blocks as statements + +@stmt [YulStatement @block variant: [YulBlock]] { + edge @block.lexical_scope -> @stmt.lexical_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 +} + +@path [YulPath . [YulPathComponent @name [YulIdentifier]]] { + node @path.lexical_scope + + node ref + attr (ref) node_reference = @name + + edge ref -> @path.lexical_scope +} + +@var_assign [YulVariableAssignmentStatement @expr expression: [YulExpression]] { + edge @expr.lexical_scope -> @var_assign.lexical_scope +} + +;;; Expressions + +@expr [YulExpression] { + node @expr.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 edc47ecd0..08089471b 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 @@ -808,6 +808,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 @@ -1066,4 +1071,102 @@ 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 + node @block.defs +} + +@block [YulBlock [YulStatements . @stmt [YulStatement]]] { + edge @stmt.lexical_scope -> @block.lexical_scope +} + +[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 +} + +;;; Blocks as statements + +@stmt [YulStatement @block variant: [YulBlock]] { + edge @block.lexical_scope -> @stmt.lexical_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 +} + +@path [YulPath . [YulPathComponent @name [YulIdentifier]]] { + node @path.lexical_scope + + node ref + attr (ref) node_reference = @name + + edge ref -> @path.lexical_scope +} + +@var_assign [YulVariableAssignmentStatement @expr expression: [YulExpression]] { + edge @expr.lexical_scope -> @var_assign.lexical_scope +} + +;;; Expressions + +@expr [YulExpression] { + node @expr.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 90396f3cc..74fa6f054 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 @@ -9,3 +9,4 @@ mod imports; mod interfaces; mod scoping; 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..75d874f87 --- /dev/null +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs @@ -0,0 +1,10 @@ +// 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 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 b38cc4af8..2a2037ff1 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 @@ -9,3 +9,4 @@ mod interfaces; mod libraries; 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..4ea316210 --- /dev/null +++ b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs @@ -0,0 +1,10 @@ +// 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 variables() -> Result<()> { + run("yul", "variables") +} diff --git a/crates/solidity/testing/snapshots/bindings_assertions/yul/variables.sol b/crates/solidity/testing/snapshots/bindings_assertions/yul/variables.sol new file mode 100644 index 000000000..167235573 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_assertions/yul/variables.sol @@ -0,0 +1,14 @@ +contract AssemblyVariables { + function yul_let(uint256 x) public returns (uint256 z) { + // ^def:2 + // ^def:1 + assembly { + let y := 123 + x + // ^ref:1 + // ^def:3 + z := 456 + y + // ^ref:3 + // Date: Tue, 20 Aug 2024 18:50:47 -0400 Subject: [PATCH 2/8] Add support for bindings in Yul expressions --- .../inputs/language/bindings/rules.msgb | 36 ++++++++++++++++--- .../bindings/generated/binding_rules.rs | 36 ++++++++++++++++--- .../src/bindings_assertions/generated/yul.rs | 5 +++ .../bindings_assertions/yul/blocks.sol | 33 +++++++++++++++++ .../bindings_assertions/yul/variables.sol | 11 +++--- 5 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/blocks.sol diff --git a/crates/solidity/inputs/language/bindings/rules.msgb b/crates/solidity/inputs/language/bindings/rules.msgb index 3f4355a09..1916ca7f7 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -1145,6 +1145,20 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @path.lexical_scope -> @var_assign.lexical_scope } +@var_assign [YulVariableAssignmentStatement @expr expression: [YulExpression]] { + edge @expr.lexical_scope -> @var_assign.lexical_scope +} + +;;; 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 @@ -1154,12 +1168,24 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge ref -> @path.lexical_scope } -@var_assign [YulVariableAssignmentStatement @expr expression: [YulExpression]] { - edge @expr.lexical_scope -> @var_assign.lexical_scope +@expr [YulExpression @funcall [YulFunctionCallExpression]] { + edge @funcall.lexical_scope -> @expr.lexical_scope } -;;; Expressions +@funcall [YulFunctionCallExpression + @operand operand: [YulExpression] + @args arguments: [YulArguments] +] { + node @funcall.lexical_scope -@expr [YulExpression] { - node @expr.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 08089471b..46f4973e8 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 @@ -1150,6 +1150,20 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @path.lexical_scope -> @var_assign.lexical_scope } +@var_assign [YulVariableAssignmentStatement @expr expression: [YulExpression]] { + edge @expr.lexical_scope -> @var_assign.lexical_scope +} + +;;; 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 @@ -1159,14 +1173,26 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge ref -> @path.lexical_scope } -@var_assign [YulVariableAssignmentStatement @expr expression: [YulExpression]] { - edge @expr.lexical_scope -> @var_assign.lexical_scope +@expr [YulExpression @funcall [YulFunctionCallExpression]] { + edge @funcall.lexical_scope -> @expr.lexical_scope } -;;; Expressions +@funcall [YulFunctionCallExpression + @operand operand: [YulExpression] + @args arguments: [YulArguments] +] { + node @funcall.lexical_scope -@expr [YulExpression] { - node @expr.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/yul.rs b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs index 75d874f87..22af228be 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs @@ -4,6 +4,11 @@ use anyhow::Result; use crate::bindings_assertions::runner::run; +#[test] +fn blocks() -> Result<()> { + run("yul", "blocks") +} + #[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 + // Date: Wed, 21 Aug 2024 11:31:33 -0400 Subject: [PATCH 3/8] Rules for name resolution in Yul functions --- .../inputs/language/bindings/rules.msgb | 55 ++++++++++++++++ .../bindings/generated/binding_rules.rs | 55 ++++++++++++++++ .../src/bindings_assertions/generated/yul.rs | 10 +++ .../src/bindings_output/generated/yul.rs | 5 ++ .../bindings_assertions/yul/fun_scopes.sol | 33 ++++++++++ .../bindings_assertions/yul/functions.sol | 32 ++++++++++ .../functions/generated/0.4.11-success.txt | 62 +++++++++++++++++++ .../bindings_output/yul/functions/input.sol | 14 +++++ 8 files changed, 266 insertions(+) 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_output/yul/functions/generated/0.4.11-success.txt create mode 100644 crates/solidity/testing/snapshots/bindings_output/yul/functions/input.sol diff --git a/crates/solidity/inputs/language/bindings/rules.msgb b/crates/solidity/inputs/language/bindings/rules.msgb index 1916ca7f7..5ea1032d0 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -1076,6 +1076,9 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @block [YulBlock] { node @block.lexical_scope node @block.defs + node @block.fundefs + + edge @block.lexical_scope -> @block.fundefs } @block [YulBlock [YulStatements . @stmt [YulStatement]]] { @@ -1099,6 +1102,12 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @block.lexical_scope -> @stmt.lexical_scope } +@parent_block [YulBlock [YulStatements [YulStatement @child_block [YulBlock]]]] { + ;; Child blocks have direct access to the parent's function definitions (to + ;; allow propagation to inner function definitions) + edge @child_block.fundefs -> @parent_block.fundefs +} + ;;; Expression as statements @stmt [YulStatement @expr_stmt [YulExpression]] { @@ -1149,6 +1158,52 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i 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.fundefs -> @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.fundefs +} + +@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 +} + ;;; Expressions @expr [YulExpression] { 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 46f4973e8..bea10bbe9 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 @@ -1081,6 +1081,9 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @block [YulBlock] { node @block.lexical_scope node @block.defs + node @block.fundefs + + edge @block.lexical_scope -> @block.fundefs } @block [YulBlock [YulStatements . @stmt [YulStatement]]] { @@ -1104,6 +1107,12 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @block.lexical_scope -> @stmt.lexical_scope } +@parent_block [YulBlock [YulStatements [YulStatement @child_block [YulBlock]]]] { + ;; Child blocks have direct access to the parent's function definitions (to + ;; allow propagation to inner function definitions) + edge @child_block.fundefs -> @parent_block.fundefs +} + ;;; Expression as statements @stmt [YulStatement @expr_stmt [YulExpression]] { @@ -1154,6 +1163,52 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i 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.fundefs -> @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.fundefs +} + +@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 +} + ;;; Expressions @expr [YulExpression] { 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 index 22af228be..45724629d 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs @@ -9,6 +9,16 @@ fn blocks() -> Result<()> { run("yul", "blocks") } +#[test] +fn fun_scopes() -> Result<()> { + run("yul", "fun_scopes") +} + +#[test] +fn functions() -> Result<()> { + run("yul", "functions") +} + #[test] fn variables() -> Result<()> { run("yul", "variables") 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 index 4ea316210..d16e315ce 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs @@ -4,6 +4,11 @@ use anyhow::Result; use crate::bindings_output::runner::run; +#[test] +fn functions() -> Result<()> { + run("yul", "functions") +} + #[test] fn variables() -> Result<()> { run("yul", "variables") diff --git a/crates/solidity/testing/snapshots/bindings_assertions/yul/fun_scopes.sol b/crates/solidity/testing/snapshots/bindings_assertions/yul/fun_scopes.sol new file mode 100644 index 000000000..7f202c679 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_assertions/yul/fun_scopes.sol @@ -0,0 +1,33 @@ +contract AssemblyFunctions { + function test(uint256 a) public returns (uint256 r) { + // ^def:4 + // ^def:3 + assembly { + { + function inner(x_i) -> x { + // ^def:1 + x := add(x_i, 1) + } + + 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_output/yul/functions/generated/0.4.11-success.txt b/crates/solidity/testing/snapshots/bindings_output/yul/functions/generated/0.4.11-success.txt new file mode 100644 index 000000000..4d553b050 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/functions/generated/0.4.11-success.txt @@ -0,0 +1,62 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +References and definitions: + ╭─[input.sol:1:1] + │ + 1 │ contract AssemblyFunctions { + │ ────────┬──────── + │ ╰────────── def: 1 + 2 │ function test(uint256 x) public returns (uint256 r) { + │ ──┬─ ┬ ┬ + │ ╰──────────────────────────────────────── def: 2 + │ │ │ + │ ╰───────────────────────────── def: 3 + │ │ + │ ╰── def: 4 + │ + 4 │ let y := add(x, 5) + │ ┬ ┬ + │ ╰─────────── def: 5 + │ │ + │ ╰── ref: 3 + 5 │ x, y := swap(x, y) + │ ┬ ┬ ──┬─ ┬ ┬ + │ ╰────────────────── ref: 3 + │ │ │ │ │ + │ ╰─────────────── ref: 5 + │ │ │ │ + │ ╰──────── ref: 6 + │ │ │ + │ ╰───── ref: 3 + │ │ + │ ╰── ref: 5 + 6 │ r := add(x, y) + │ ┬ ┬ ┬ + │ ╰────────────── ref: 4 + │ │ │ + │ ╰───── ref: 3 + │ │ + │ ╰── ref: 5 + │ + 8 │ function swap(a, b) -> 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 + } + } + } +} From fa7927efd97762b9acdf8d94654db6cd41b0dfbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 21 Aug 2024 12:04:14 -0400 Subject: [PATCH 4/8] Yul stack assignment binding rule --- crates/solidity/inputs/language/bindings/rules.msgb | 9 +++++++++ .../src/generated/bindings/generated/binding_rules.rs | 9 +++++++++ .../tests/src/bindings_assertions/generated/yul.rs | 5 +++++ .../bindings_assertions/yul/stack_assign.sol | 11 +++++++++++ 4 files changed, 34 insertions(+) create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/stack_assign.sol diff --git a/crates/solidity/inputs/language/bindings/rules.msgb b/crates/solidity/inputs/language/bindings/rules.msgb index 5ea1032d0..7f021383b 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -1204,6 +1204,15 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @fundef.lexical_scope -> def } +;;; (Deprecated) Stack assignment + +@stmt [YulStatement [YulStackAssignmentStatement @name [YulIdentifier]]] { + node ref + attr (ref) node_reference = @name + + edge ref -> @stmt.lexical_scope +} + ;;; Expressions @expr [YulExpression] { 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 bea10bbe9..d92e49a59 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 @@ -1209,6 +1209,15 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @fundef.lexical_scope -> def } +;;; (Deprecated) Stack assignment + +@stmt [YulStatement [YulStackAssignmentStatement @name [YulIdentifier]]] { + node ref + attr (ref) node_reference = @name + + edge ref -> @stmt.lexical_scope +} + ;;; Expressions @expr [YulExpression] { 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 index 45724629d..fd8d172aa 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs @@ -19,6 +19,11 @@ fn functions() -> Result<()> { run("yul", "functions") } +#[test] +fn stack_assign() -> Result<()> { + run("yul", "stack_assign") +} + #[test] fn variables() -> Result<()> { run("yul", "variables") diff --git a/crates/solidity/testing/snapshots/bindings_assertions/yul/stack_assign.sol b/crates/solidity/testing/snapshots/bindings_assertions/yul/stack_assign.sol new file mode 100644 index 000000000..a48969a6f --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_assertions/yul/stack_assign.sol @@ -0,0 +1,11 @@ +contract YulStackAssignment { + function test() public { + assembly { + let x := 0 + // ^def:1 + sload(10) + =: x + // ^ref:1 (< 0.5.0) + } + } +} From 16aa76604e31d8ea4dd8bd64830debe51ab4a7e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 21 Aug 2024 12:42:29 -0400 Subject: [PATCH 5/8] Rules for bindings in Yul conditionals --- .../inputs/language/bindings/rules.msgb | 41 +++++++++++++++--- .../bindings/generated/binding_rules.rs | 41 +++++++++++++++--- .../src/bindings_assertions/generated/yul.rs | 5 +++ .../src/bindings_output/generated/yul.rs | 5 +++ .../bindings_assertions/yul/fun_scopes.sol | 3 +- .../bindings_assertions/yul/if_stmt.sol | 19 ++++++++ .../conditionals/generated/0.4.11-success.txt | 43 +++++++++++++++++++ .../yul/conditionals/input.sol | 16 +++++++ 8 files changed, 160 insertions(+), 13 deletions(-) create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/if_stmt.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 diff --git a/crates/solidity/inputs/language/bindings/rules.msgb b/crates/solidity/inputs/language/bindings/rules.msgb index 7f021383b..7bd80ef19 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -1085,6 +1085,10 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @stmt.lexical_scope -> @block.lexical_scope } +@block [YulBlock [YulStatements @stmt [YulStatement]]] { + edge @stmt.fun_scope -> @block.fundefs +} + [YulStatements @left_stmt [YulStatement] . @right_stmt [YulStatement]] { edge @right_stmt.lexical_scope -> @left_stmt.lexical_scope ; variable declaration are accessible from the next statement @@ -1094,18 +1098,17 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @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.fun_scope } ;;; Blocks as statements @stmt [YulStatement @block variant: [YulBlock]] { edge @block.lexical_scope -> @stmt.lexical_scope -} - -@parent_block [YulBlock [YulStatements [YulStatement @child_block [YulBlock]]]] { - ;; Child blocks have direct access to the parent's function definitions (to - ;; allow propagation to inner function definitions) - edge @child_block.fundefs -> @parent_block.fundefs + edge @block.fundefs -> @stmt.fun_scope } ;;; Expression as statements @@ -1213,6 +1216,32 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i 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.fundefs -> @stmt.fun_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.fundefs -> @stmt.fun_scope +} + ;;; Expressions @expr [YulExpression] { 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 d92e49a59..14345c29d 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 @@ -1090,6 +1090,10 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @stmt.lexical_scope -> @block.lexical_scope } +@block [YulBlock [YulStatements @stmt [YulStatement]]] { + edge @stmt.fun_scope -> @block.fundefs +} + [YulStatements @left_stmt [YulStatement] . @right_stmt [YulStatement]] { edge @right_stmt.lexical_scope -> @left_stmt.lexical_scope ; variable declaration are accessible from the next statement @@ -1099,18 +1103,17 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @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.fun_scope } ;;; Blocks as statements @stmt [YulStatement @block variant: [YulBlock]] { edge @block.lexical_scope -> @stmt.lexical_scope -} - -@parent_block [YulBlock [YulStatements [YulStatement @child_block [YulBlock]]]] { - ;; Child blocks have direct access to the parent's function definitions (to - ;; allow propagation to inner function definitions) - edge @child_block.fundefs -> @parent_block.fundefs + edge @block.fundefs -> @stmt.fun_scope } ;;; Expression as statements @@ -1218,6 +1221,32 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i 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.fundefs -> @stmt.fun_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.fundefs -> @stmt.fun_scope +} + ;;; Expressions @expr [YulExpression] { 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 index fd8d172aa..3c8cad7fb 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs @@ -19,6 +19,11 @@ fn functions() -> Result<()> { run("yul", "functions") } +#[test] +fn if_stmt() -> Result<()> { + run("yul", "if_stmt") +} + #[test] fn stack_assign() -> Result<()> { run("yul", "stack_assign") 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 index d16e315ce..cb1f42435 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs @@ -4,6 +4,11 @@ use anyhow::Result; use crate::bindings_output::runner::run; +#[test] +fn conditionals() -> Result<()> { + run("yul", "conditionals") +} + #[test] fn functions() -> Result<()> { run("yul", "functions") diff --git a/crates/solidity/testing/snapshots/bindings_assertions/yul/fun_scopes.sol b/crates/solidity/testing/snapshots/bindings_assertions/yul/fun_scopes.sol index 7f202c679..c9bd4728d 100644 --- a/crates/solidity/testing/snapshots/bindings_assertions/yul/fun_scopes.sol +++ b/crates/solidity/testing/snapshots/bindings_assertions/yul/fun_scopes.sol @@ -6,7 +6,8 @@ contract AssemblyFunctions { { function inner(x_i) -> x { // ^def:1 - x := add(x_i, 1) + x := add(x_i, outer()) + // ^ref:2 } r := inner(a) 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_output/yul/conditionals/generated/0.4.11-success.txt b/crates/solidity/testing/snapshots/bindings_output/yul/conditionals/generated/0.4.11-success.txt new file mode 100644 index 000000000..366fb1089 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/conditionals/generated/0.4.11-success.txt @@ -0,0 +1,43 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +References and definitions: + ╭─[input.sol:1:1] + │ + 1 │ contract AssemblyConditionals { + │ ──────────┬───────── + │ ╰─────────── def: 1 + 2 │ function yul_if(uint256 x) public returns (uint256 z) { + │ ───┬── ┬ ┬ + │ ╰───────────────────────────────────────── def: 2 + │ │ │ + │ ╰───────────────────────────── def: 3 + │ │ + │ ╰── def: 4 + │ + 4 │ if lt(x, 10) { z := 99 } + │ ┬ ┬ + │ ╰─────────── ref: 3 + │ │ + │ ╰── ref: 4 + │ + 8 │ function yul_switch(uint256 x) public returns (uint256 z) { + │ ─────┬──── ┬ ┬ + │ ╰─────────────────────────────────────────── def: 5 + │ │ │ + │ ╰───────────────────────────── def: 6 + │ │ + │ ╰── def: 7 + │ + 10 │ switch x + │ ┬ + │ ╰── ref: 6 + 11 │ case 1 { z := 10 } + │ ┬ + │ ╰── ref: 7 + 12 │ case 2 { z := 20 } + │ ┬ + │ ╰── ref: 7 + 13 │ default { z := 0 } + │ ┬ + │ ╰── ref: 7 +────╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/yul/conditionals/input.sol b/crates/solidity/testing/snapshots/bindings_output/yul/conditionals/input.sol new file mode 100644 index 000000000..8004bd08f --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/yul/conditionals/input.sol @@ -0,0 +1,16 @@ +contract AssemblyConditionals { + function yul_if(uint256 x) public returns (uint256 z) { + assembly { + if lt(x, 10) { z := 99 } + } + } + + function yul_switch(uint256 x) public returns (uint256 z) { + assembly { + switch x + case 1 { z := 10 } + case 2 { z := 20 } + default { z := 0 } + } + } +} From 7cc66df374ee1894d42ad569d6190532b8cf958a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 21 Aug 2024 15:33:05 -0400 Subject: [PATCH 6/8] Resolve bindings in Yul for statements --- .../inputs/language/bindings/rules.msgb | 22 ++++++++ .../bindings/generated/binding_rules.rs | 22 ++++++++ .../src/bindings_output/generated/yul.rs | 5 ++ .../yul/loops/generated/0.4.11-success.txt | 51 +++++++++++++++++++ .../bindings_output/yul/loops/input.sol | 17 +++++++ 5 files changed, 117 insertions(+) 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 diff --git a/crates/solidity/inputs/language/bindings/rules.msgb b/crates/solidity/inputs/language/bindings/rules.msgb index 7bd80ef19..71cce494c 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -1075,7 +1075,11 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @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.defs + ; Function definitions accessible from the block (ie. defined in the block, or + ; accessible in the enclosing parent block) node @block.fundefs edge @block.lexical_scope -> @block.fundefs @@ -1087,6 +1091,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @block [YulBlock [YulStatements @stmt [YulStatement]]] { edge @stmt.fun_scope -> @block.fundefs + edge @block.defs -> @stmt.defs } [YulStatements @left_stmt [YulStatement] . @right_stmt [YulStatement]] { @@ -1242,6 +1247,23 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @body.fundefs -> @stmt.fun_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 @cond.lexical_scope -> @init.defs + edge @iter.lexical_scope -> @stmt.lexical_scope + edge @iter.lexical_scope -> @init.defs + edge @body.lexical_scope -> @stmt.lexical_scope + edge @body.lexical_scope -> @init.defs +} + ;;; Expressions @expr [YulExpression] { 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 14345c29d..ca5ace731 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 @@ -1080,7 +1080,11 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @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.defs + ; Function definitions accessible from the block (ie. defined in the block, or + ; accessible in the enclosing parent block) node @block.fundefs edge @block.lexical_scope -> @block.fundefs @@ -1092,6 +1096,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @block [YulBlock [YulStatements @stmt [YulStatement]]] { edge @stmt.fun_scope -> @block.fundefs + edge @block.defs -> @stmt.defs } [YulStatements @left_stmt [YulStatement] . @right_stmt [YulStatement]] { @@ -1247,6 +1252,23 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @body.fundefs -> @stmt.fun_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 @cond.lexical_scope -> @init.defs + edge @iter.lexical_scope -> @stmt.lexical_scope + edge @iter.lexical_scope -> @init.defs + edge @body.lexical_scope -> @stmt.lexical_scope + edge @body.lexical_scope -> @init.defs +} + ;;; Expressions @expr [YulExpression] { 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 index cb1f42435..be4e18498 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/yul.rs @@ -14,6 +14,11 @@ 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_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) + } + } + } +} From 1997c6729ae60f34becce8fa7cc646e70ded36d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Gir=C3=A1ldez?= Date: Wed, 21 Aug 2024 15:51:36 -0400 Subject: [PATCH 7/8] Add rules for (deprecated) Yul labels --- .../inputs/language/bindings/rules.msgb | 11 +++++++++ .../bindings/generated/binding_rules.rs | 11 +++++++++ .../src/bindings_assertions/generated/yul.rs | 5 ++++ .../bindings_assertions/yul/labels.sol | 24 +++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 crates/solidity/testing/snapshots/bindings_assertions/yul/labels.sol diff --git a/crates/solidity/inputs/language/bindings/rules.msgb b/crates/solidity/inputs/language/bindings/rules.msgb index 71cce494c..b7fbd5881 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -1264,6 +1264,17 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @body.lexical_scope -> @init.defs } +;;; (Deprecated) Label statements + +@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] { 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 ca5ace731..a76392a25 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 @@ -1269,6 +1269,17 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @body.lexical_scope -> @init.defs } +;;; (Deprecated) Label statements + +@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] { 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 index 3c8cad7fb..e324fe909 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/yul.rs @@ -24,6 +24,11 @@ fn if_stmt() -> Result<()> { run("yul", "if_stmt") } +#[test] +fn labels() -> Result<()> { + run("yul", "labels") +} + #[test] fn stack_assign() -> Result<()> { run("yul", "stack_assign") 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: + // Date: Thu, 22 Aug 2024 17:08:51 -0400 Subject: [PATCH 8/8] Address code review suggestions by improving names of some scoped nodes --- .../inputs/language/bindings/rules.msgb | 33 ++++++++++--------- .../bindings/generated/binding_rules.rs | 33 ++++++++++--------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/crates/solidity/inputs/language/bindings/rules.msgb b/crates/solidity/inputs/language/bindings/rules.msgb index b7fbd5881..ebfad82d0 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -1077,12 +1077,12 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i node @block.lexical_scope ; Variables defined in this block (only used to forward the init block ; declarations in a for statement) - node @block.defs + node @block.variable_defs ; Function definitions accessible from the block (ie. defined in the block, or ; accessible in the enclosing parent block) - node @block.fundefs + node @block.function_defs - edge @block.lexical_scope -> @block.fundefs + edge @block.lexical_scope -> @block.function_defs } @block [YulBlock [YulStatements . @stmt [YulStatement]]] { @@ -1090,8 +1090,8 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i } @block [YulBlock [YulStatements @stmt [YulStatement]]] { - edge @stmt.fun_scope -> @block.fundefs - edge @block.defs -> @stmt.defs + edge @stmt.function_scope -> @block.function_defs + edge @block.variable_defs -> @stmt.defs } [YulStatements @left_stmt [YulStatement] . @right_stmt [YulStatement]] { @@ -1106,14 +1106,14 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i ;; Functions visible in this scope (to propagate to inner function ;; definitions, since the lexical scope is not accessible inside a function ;; body) - node @stmt.fun_scope + node @stmt.function_scope } ;;; Blocks as statements @stmt [YulStatement @block variant: [YulBlock]] { edge @block.lexical_scope -> @stmt.lexical_scope - edge @block.fundefs -> @stmt.fun_scope + edge @block.function_defs -> @stmt.function_scope } ;;; Expression as statements @@ -1170,11 +1170,11 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @block [YulBlock [YulStatements [YulStatement @fundef [YulFunctionDefinition]]]] { ;; Function definitions are hoisted in the enclosing block - edge @block.fundefs -> @fundef.def + 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.fundefs + edge @fundef.lexical_scope -> @block.function_defs } @fundef [YulFunctionDefinition @@ -1212,7 +1212,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @fundef.lexical_scope -> def } -;;; (Deprecated) Stack assignment +;;; Stack assignment (Solidity < 0.5.0) @stmt [YulStatement [YulStackAssignmentStatement @name [YulIdentifier]]] { node ref @@ -1229,7 +1229,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i ]] { edge @condition.lexical_scope -> @stmt.lexical_scope edge @body.lexical_scope -> @stmt.lexical_scope - edge @body.fundefs -> @stmt.fun_scope + edge @body.function_defs -> @stmt.function_scope } ;;; Switch statements @@ -1244,7 +1244,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i [_ @body body: [YulBlock]] ]]]] { edge @body.lexical_scope -> @stmt.lexical_scope - edge @body.fundefs -> @stmt.fun_scope + edge @body.function_defs -> @stmt.function_scope } ;;; For statements @@ -1257,14 +1257,15 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i ]] { edge @init.lexical_scope -> @stmt.lexical_scope edge @cond.lexical_scope -> @stmt.lexical_scope - edge @cond.lexical_scope -> @init.defs edge @iter.lexical_scope -> @stmt.lexical_scope - edge @iter.lexical_scope -> @init.defs edge @body.lexical_scope -> @stmt.lexical_scope - edge @body.lexical_scope -> @init.defs + + edge @cond.lexical_scope -> @init.variable_defs + edge @iter.lexical_scope -> @init.variable_defs + edge @body.lexical_scope -> @init.variable_defs } -;;; (Deprecated) Label statements +;;; Label statements (Solidity < 0.5.0) @block [YulBlock [YulStatements [YulStatement @label [YulLabel @name label: [YulIdentifier]]]]] { node def 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 a76392a25..83ed7a08b 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 @@ -1082,12 +1082,12 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i node @block.lexical_scope ; Variables defined in this block (only used to forward the init block ; declarations in a for statement) - node @block.defs + node @block.variable_defs ; Function definitions accessible from the block (ie. defined in the block, or ; accessible in the enclosing parent block) - node @block.fundefs + node @block.function_defs - edge @block.lexical_scope -> @block.fundefs + edge @block.lexical_scope -> @block.function_defs } @block [YulBlock [YulStatements . @stmt [YulStatement]]] { @@ -1095,8 +1095,8 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i } @block [YulBlock [YulStatements @stmt [YulStatement]]] { - edge @stmt.fun_scope -> @block.fundefs - edge @block.defs -> @stmt.defs + edge @stmt.function_scope -> @block.function_defs + edge @block.variable_defs -> @stmt.defs } [YulStatements @left_stmt [YulStatement] . @right_stmt [YulStatement]] { @@ -1111,14 +1111,14 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i ;; Functions visible in this scope (to propagate to inner function ;; definitions, since the lexical scope is not accessible inside a function ;; body) - node @stmt.fun_scope + node @stmt.function_scope } ;;; Blocks as statements @stmt [YulStatement @block variant: [YulBlock]] { edge @block.lexical_scope -> @stmt.lexical_scope - edge @block.fundefs -> @stmt.fun_scope + edge @block.function_defs -> @stmt.function_scope } ;;; Expression as statements @@ -1175,11 +1175,11 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i @block [YulBlock [YulStatements [YulStatement @fundef [YulFunctionDefinition]]]] { ;; Function definitions are hoisted in the enclosing block - edge @block.fundefs -> @fundef.def + 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.fundefs + edge @fundef.lexical_scope -> @block.function_defs } @fundef [YulFunctionDefinition @@ -1217,7 +1217,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @fundef.lexical_scope -> def } -;;; (Deprecated) Stack assignment +;;; Stack assignment (Solidity < 0.5.0) @stmt [YulStatement [YulStackAssignmentStatement @name [YulIdentifier]]] { node ref @@ -1234,7 +1234,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i ]] { edge @condition.lexical_scope -> @stmt.lexical_scope edge @body.lexical_scope -> @stmt.lexical_scope - edge @body.fundefs -> @stmt.fun_scope + edge @body.function_defs -> @stmt.function_scope } ;;; Switch statements @@ -1249,7 +1249,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i [_ @body body: [YulBlock]] ]]]] { edge @body.lexical_scope -> @stmt.lexical_scope - edge @body.fundefs -> @stmt.fun_scope + edge @body.function_defs -> @stmt.function_scope } ;;; For statements @@ -1262,14 +1262,15 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i ]] { edge @init.lexical_scope -> @stmt.lexical_scope edge @cond.lexical_scope -> @stmt.lexical_scope - edge @cond.lexical_scope -> @init.defs edge @iter.lexical_scope -> @stmt.lexical_scope - edge @iter.lexical_scope -> @init.defs edge @body.lexical_scope -> @stmt.lexical_scope - edge @body.lexical_scope -> @init.defs + + edge @cond.lexical_scope -> @init.variable_defs + edge @iter.lexical_scope -> @init.variable_defs + edge @body.lexical_scope -> @init.variable_defs } -;;; (Deprecated) Label statements +;;; Label statements (Solidity < 0.5.0) @block [YulBlock [YulStatements [YulStatement @label [YulLabel @name label: [YulIdentifier]]]]] { node def