Skip to content

Commit

Permalink
Binding rules for inline assembly (NomicFoundation#1087)
Browse files Browse the repository at this point in the history
Adds binding rules to support inline Yul assembly
  • Loading branch information
ggiraldez committed Aug 23, 2024
1 parent f749e53 commit 8c3c13a
Show file tree
Hide file tree
Showing 21 changed files with 981 additions and 0 deletions.
256 changes: 256 additions & 0 deletions crates/solidity/inputs/language/bindings/rules.msgb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Loading

0 comments on commit 8c3c13a

Please sign in to comment.