Skip to content

Commit

Permalink
Rules for name resolution in Yul functions
Browse files Browse the repository at this point in the history
  • Loading branch information
ggiraldez committed Aug 21, 2024
1 parent 2a7ffaf commit 0238bb5
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 0 deletions.
55 changes: 55 additions & 0 deletions crates/solidity/inputs/language/bindings/rules.msgb
Original file line number Diff line number Diff line change
Expand Up @@ -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]]] {
Expand All @@ -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]] {
Expand Down Expand Up @@ -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] {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -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
//<ref:4
}

let z := 1
// ^def:5

function outer() -> y {
// ^def:2
y := inner()
// ^ref:! -- function is not visible here
r := add(a, 1)
// ^ref:! -- assembly functions cannot access Solidity variables
//<ref:!
y := z
// ^ref:! -- vars declared outside the function are not visible either
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
contract AssemblyFunctions {
function test(uint256 x) public returns (uint256 r) {
assembly {
function outer1(a) -> 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
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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
────╯
Original file line number Diff line number Diff line change
@@ -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
}
}
}
}

0 comments on commit 0238bb5

Please sign in to comment.