Przeglądaj źródła

Integrate inline assembly to graphviz (#716)

Signed-off-by: Lucas Steuernagel <lucas.tnagel@gmail.com>
Lucas Steuernagel 3 lat temu
rodzic
commit
13f2efac40

+ 7 - 0
src/bin/solang.rs

@@ -335,6 +335,8 @@ fn main() {
             if matches.is_present("STD-JSON") {
                 println!("{}", serde_json::to_string(&json).unwrap());
                 std::process::exit(0);
+            } else if let Some("ast-dot") = matches.value_of("EMIT") {
+                std::process::exit(0);
             } else {
                 eprintln!("error: not all contracts are valid");
                 std::process::exit(1);
@@ -468,6 +470,11 @@ fn process_file(
             eprintln!("{}: error: {}", dot_filename.display(), err);
             std::process::exit(1);
         }
+
+        if ns.contracts.is_empty() || diagnostics::any_errors(&ns.diagnostics) {
+            return Err(());
+        }
+
         return Ok(ns);
     }
 

+ 125 - 0
src/sema/assembly/ast.rs

@@ -0,0 +1,125 @@
+use crate::ast::Type;
+use crate::sema::assembly::builtin::AssemblyBuiltInFunction;
+use crate::sema::symtable::Symtable;
+use num_bigint::BigInt;
+use solang_parser::pt;
+use solang_parser::pt::{CodeLocation, StorageLocation};
+use std::sync::Arc;
+
+#[derive(Debug, Clone)]
+pub struct InlineAssembly {
+    pub loc: pt::Loc,
+    pub body: Vec<(AssemblyStatement, bool)>,
+    pub functions: Vec<AssemblyFunction>,
+}
+
+#[derive(Debug, Clone)]
+pub struct AssemblyBlock {
+    pub loc: pt::Loc,
+    pub body: Vec<(AssemblyStatement, bool)>,
+}
+
+#[derive(PartialEq, Debug, Clone)]
+pub enum AssemblyExpression {
+    BoolLiteral(pt::Loc, bool, Type),
+    NumberLiteral(pt::Loc, BigInt, Type),
+    StringLiteral(pt::Loc, Vec<u8>, Type),
+    AssemblyLocalVariable(pt::Loc, Type, usize),
+    SolidityLocalVariable(pt::Loc, Type, Option<StorageLocation>, usize),
+    ConstantVariable(pt::Loc, Type, Option<usize>, usize),
+    StorageVariable(pt::Loc, Type, usize, usize),
+    BuiltInCall(pt::Loc, AssemblyBuiltInFunction, Vec<AssemblyExpression>),
+    FunctionCall(pt::Loc, usize, Vec<AssemblyExpression>),
+    MemberAccess(pt::Loc, Box<AssemblyExpression>, AssemblySuffix),
+}
+
+#[derive(PartialEq, Debug, Clone)]
+pub enum AssemblySuffix {
+    Offset,
+    Slot,
+    Length,
+    Selector,
+    Address,
+}
+
+impl ToString for AssemblySuffix {
+    fn to_string(&self) -> String {
+        let name = match self {
+            AssemblySuffix::Offset => "offset",
+            AssemblySuffix::Slot => "slot",
+            AssemblySuffix::Length => "length",
+            AssemblySuffix::Selector => "selector",
+            AssemblySuffix::Address => "address",
+        };
+
+        name.to_string()
+    }
+}
+
+impl CodeLocation for AssemblyExpression {
+    fn loc(&self) -> pt::Loc {
+        match self {
+            AssemblyExpression::BoolLiteral(loc, ..)
+            | AssemblyExpression::NumberLiteral(loc, ..)
+            | AssemblyExpression::StringLiteral(loc, ..)
+            | AssemblyExpression::AssemblyLocalVariable(loc, ..)
+            | AssemblyExpression::SolidityLocalVariable(loc, ..)
+            | AssemblyExpression::ConstantVariable(loc, ..)
+            | AssemblyExpression::StorageVariable(loc, ..)
+            | AssemblyExpression::BuiltInCall(loc, ..)
+            | AssemblyExpression::MemberAccess(loc, ..)
+            | AssemblyExpression::FunctionCall(loc, ..) => *loc,
+        }
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct AssemblyFunction {
+    pub loc: pt::Loc,
+    pub name: String,
+    pub params: Arc<Vec<AssemblyFunctionParameter>>,
+    pub returns: Arc<Vec<AssemblyFunctionParameter>>,
+    pub body: Vec<(AssemblyStatement, bool)>,
+    pub symtable: Symtable,
+    pub called: bool,
+}
+
+#[derive(Debug, Clone)]
+pub struct AssemblyFunctionParameter {
+    pub loc: pt::Loc,
+    pub id: pt::Identifier,
+    pub ty: Type,
+}
+
+#[derive(Clone, Debug)]
+pub enum AssemblyStatement {
+    FunctionCall(pt::Loc, usize, Vec<AssemblyExpression>),
+    BuiltInCall(pt::Loc, AssemblyBuiltInFunction, Vec<AssemblyExpression>),
+    Block(Box<AssemblyBlock>),
+    VariableDeclaration(pt::Loc, Vec<usize>, Option<AssemblyExpression>),
+    Assignment(pt::Loc, Vec<AssemblyExpression>, AssemblyExpression),
+    IfBlock(pt::Loc, AssemblyExpression, Box<AssemblyBlock>),
+    Switch {
+        loc: pt::Loc,
+        condition: AssemblyExpression,
+        cases: Vec<CaseBlock>,
+        default: Option<AssemblyBlock>,
+    },
+    For {
+        loc: pt::Loc,
+        init_block: AssemblyBlock,
+        condition: AssemblyExpression,
+        post_block: AssemblyBlock,
+        execution_block: AssemblyBlock,
+    },
+    Leave(pt::Loc),
+    Break(pt::Loc),
+    Continue(pt::Loc),
+}
+
+#[derive(Debug, Clone)]
+pub struct CaseBlock {
+    pub loc: pt::Loc,
+    pub condition: AssemblyExpression,
+    pub block: AssemblyBlock,
+}

+ 2 - 7
src/sema/assembly/block.rs

@@ -1,18 +1,13 @@
 use crate::ast::Namespace;
+use crate::sema::assembly::ast::{AssemblyBlock, AssemblyStatement};
 use crate::sema::assembly::functions::{
     process_function_header, resolve_function_definition, FunctionsTable,
 };
-use crate::sema::assembly::statements::{resolve_assembly_statement, AssemblyStatement};
+use crate::sema::assembly::statements::resolve_assembly_statement;
 use crate::sema::expression::ExprContext;
 use crate::sema::symtable::{LoopScopes, Symtable};
 use solang_parser::{pt, Diagnostic};
 
-#[derive(Debug, Clone)]
-pub struct AssemblyBlock {
-    pub loc: pt::Loc,
-    pub body: Vec<(AssemblyStatement, bool)>,
-}
-
 /// Resolve an assembly block.
 /// Returns the resolved block and a boolean that tells us if the next statement is reachable.
 pub fn resolve_assembly_block(

+ 7 - 0
src/sema/assembly/builtin.rs

@@ -194,6 +194,13 @@ impl AssemblyBuiltInFunction {
     }
 }
 
+impl ToString for AssemblyBuiltInFunction {
+    fn to_string(&self) -> String {
+        let prototype = self.get_prototype_info();
+        prototype.name.to_owned()
+    }
+}
+
 // Assembly built-in functions.
 // Descriptions copied and slightly modified from: https://docs.soliditylang.org/en/v0.8.12/yul.html
 static ASSEMBLY_BUILTIN: [AssemblyBuiltinPrototype; 76] =

+ 3 - 44
src/sema/assembly/expression.rs

@@ -1,8 +1,7 @@
 use crate::ast::{Namespace, Symbol, Type};
-use crate::sema::assembly::builtin::{
-    assembly_unsupported_builtin, parse_builtin_keyword, AssemblyBuiltInFunction,
-};
-use crate::sema::assembly::functions::{AssemblyFunctionParameter, FunctionsTable};
+use crate::sema::assembly::ast::{AssemblyExpression, AssemblyFunctionParameter, AssemblySuffix};
+use crate::sema::assembly::builtin::{assembly_unsupported_builtin, parse_builtin_keyword};
+use crate::sema::assembly::functions::FunctionsTable;
 use crate::sema::assembly::types::{
     get_default_type_from_identifier, get_type_from_string, verify_type_from_expression,
 };
@@ -15,29 +14,6 @@ use solang_parser::diagnostics::{ErrorType, Level};
 use solang_parser::pt::{AssemblyFunctionCall, CodeLocation, Identifier, Loc, StorageLocation};
 use solang_parser::{pt, Diagnostic};
 
-#[derive(PartialEq, Debug, Clone)]
-pub enum AssemblyExpression {
-    BoolLiteral(pt::Loc, bool, Type),
-    NumberLiteral(pt::Loc, BigInt, Type),
-    StringLiteral(pt::Loc, Vec<u8>, Type),
-    AssemblyLocalVariable(pt::Loc, Type, usize),
-    SolidityLocalVariable(pt::Loc, Type, Option<StorageLocation>, usize),
-    ConstantVariable(pt::Loc, Type, Option<usize>, usize),
-    StorageVariable(pt::Loc, Type, usize, usize),
-    BuiltInCall(pt::Loc, AssemblyBuiltInFunction, Vec<AssemblyExpression>),
-    FunctionCall(pt::Loc, usize, Vec<AssemblyExpression>),
-    MemberAccess(pt::Loc, Box<AssemblyExpression>, AssemblySuffix),
-}
-
-#[derive(PartialEq, Debug, Clone)]
-pub enum AssemblySuffix {
-    Offset,
-    Slot,
-    Length,
-    Selector,
-    Address,
-}
-
 /// Given a keyword, returns the suffix it represents in YUL
 fn get_suffix_from_string(suffix_name: &str) -> Option<AssemblySuffix> {
     match suffix_name {
@@ -50,23 +26,6 @@ fn get_suffix_from_string(suffix_name: &str) -> Option<AssemblySuffix> {
     }
 }
 
-impl CodeLocation for AssemblyExpression {
-    fn loc(&self) -> pt::Loc {
-        match self {
-            AssemblyExpression::BoolLiteral(loc, ..)
-            | AssemblyExpression::NumberLiteral(loc, ..)
-            | AssemblyExpression::StringLiteral(loc, ..)
-            | AssemblyExpression::AssemblyLocalVariable(loc, ..)
-            | AssemblyExpression::SolidityLocalVariable(loc, ..)
-            | AssemblyExpression::ConstantVariable(loc, ..)
-            | AssemblyExpression::StorageVariable(loc, ..)
-            | AssemblyExpression::BuiltInCall(loc, ..)
-            | AssemblyExpression::MemberAccess(loc, ..)
-            | AssemblyExpression::FunctionCall(loc, ..) => *loc,
-        }
-    }
-}
-
 /// Resolve an assembly expression.
 pub(crate) fn resolve_assembly_expression(
     expr: &pt::AssemblyExpression,

+ 2 - 2
src/sema/assembly/for_loop.rs

@@ -1,7 +1,7 @@
 use crate::ast::Namespace;
-use crate::sema::assembly::block::{process_statements, resolve_assembly_block, AssemblyBlock};
+use crate::sema::assembly::ast::{AssemblyBlock, AssemblyStatement};
+use crate::sema::assembly::block::{process_statements, resolve_assembly_block};
 use crate::sema::assembly::functions::FunctionsTable;
-use crate::sema::assembly::statements::AssemblyStatement;
 use crate::sema::assembly::switch::resolve_condition;
 use crate::sema::expression::ExprContext;
 use crate::sema::symtable::{LoopScopes, Symtable};

+ 1 - 19
src/sema/assembly/functions.rs

@@ -1,8 +1,8 @@
 use crate::ast::{Namespace, Type};
+use crate::sema::assembly::ast::{AssemblyFunction, AssemblyFunctionParameter};
 use crate::sema::assembly::block::process_statements;
 use crate::sema::assembly::builtin::{assembly_unsupported_builtin, parse_builtin_keyword};
 use crate::sema::assembly::types::get_type_from_string;
-use crate::sema::assembly::AssemblyStatement;
 use crate::sema::expression::ExprContext;
 use crate::sema::symtable::{LoopScopes, Symtable, VariableInitializer, VariableUsage};
 use solang_parser::diagnostics::{ErrorType, Level, Note};
@@ -11,24 +11,6 @@ use solang_parser::{pt, Diagnostic};
 use std::collections::{HashMap, LinkedList};
 use std::sync::Arc;
 
-#[derive(Debug, Clone)]
-pub struct AssemblyFunction {
-    pub loc: pt::Loc,
-    pub name: String,
-    pub params: Arc<Vec<AssemblyFunctionParameter>>,
-    pub returns: Arc<Vec<AssemblyFunctionParameter>>,
-    pub body: Vec<(AssemblyStatement, bool)>,
-    pub symtable: Symtable,
-    pub called: bool,
-}
-
-#[derive(Debug, Clone)]
-pub struct AssemblyFunctionParameter {
-    pub loc: pt::Loc,
-    pub id: pt::Identifier,
-    pub ty: Type,
-}
-
 /// Saves resolved function headers, so that we can account for function calls, before
 /// resolving the function's body
 pub struct FunctionHeader {

+ 4 - 12
src/sema/assembly/mod.rs

@@ -1,13 +1,14 @@
 use crate::ast::Namespace;
+use crate::sema::assembly::ast::InlineAssembly;
 use crate::sema::assembly::block::process_statements;
-use crate::sema::assembly::functions::{AssemblyFunction, FunctionsTable};
-use crate::sema::assembly::statements::AssemblyStatement;
+use crate::sema::assembly::functions::FunctionsTable;
 use crate::sema::expression::ExprContext;
 use crate::sema::symtable::{LoopScopes, Symtable};
 use solang_parser::pt;
 
+pub mod ast;
 mod block;
-mod builtin;
+pub mod builtin;
 mod expression;
 mod for_loop;
 mod functions;
@@ -17,15 +18,6 @@ mod tests;
 mod types;
 mod unused_variable;
 
-// TODO: Mark functions as used/unused
-
-#[derive(Debug, Clone)]
-pub struct InlineAssembly {
-    pub loc: pt::Loc,
-    pub body: Vec<(AssemblyStatement, bool)>,
-    pub functions: Vec<AssemblyFunction>,
-}
-
 /// Resolves a block of inline assembly
 /// Returns the resolved block and a bool to indicate if the next statement is reachable.
 pub fn resolve_inline_assembly(

+ 6 - 36
src/sema/assembly/statements.rs

@@ -1,14 +1,13 @@
 use crate::ast::Namespace;
-use crate::sema::assembly::block::{resolve_assembly_block, AssemblyBlock};
-use crate::sema::assembly::builtin::{
-    assembly_unsupported_builtin, parse_builtin_keyword, AssemblyBuiltInFunction,
-};
+use crate::sema::assembly::ast::{AssemblyExpression, AssemblyStatement};
+use crate::sema::assembly::block::resolve_assembly_block;
+use crate::sema::assembly::builtin::{assembly_unsupported_builtin, parse_builtin_keyword};
 use crate::sema::assembly::expression::{
-    check_type, resolve_assembly_expression, resolve_function_call, AssemblyExpression,
+    check_type, resolve_assembly_expression, resolve_function_call,
 };
 use crate::sema::assembly::for_loop::resolve_for_loop;
 use crate::sema::assembly::functions::FunctionsTable;
-use crate::sema::assembly::switch::{resolve_condition, resolve_switch, CaseBlock};
+use crate::sema::assembly::switch::{resolve_condition, resolve_switch};
 use crate::sema::assembly::types::get_default_type_from_identifier;
 use crate::sema::expression::ExprContext;
 use crate::sema::symtable::{LoopScopes, Symtable, VariableInitializer, VariableUsage};
@@ -16,32 +15,6 @@ use solang_parser::diagnostics::{ErrorType, Level, Note};
 use solang_parser::pt::AssemblyTypedIdentifier;
 use solang_parser::{pt, Diagnostic};
 
-#[derive(Clone, Debug)]
-pub enum AssemblyStatement {
-    FunctionCall(pt::Loc, usize, Vec<AssemblyExpression>),
-    BuiltInCall(pt::Loc, AssemblyBuiltInFunction, Vec<AssemblyExpression>),
-    Block(pt::Loc, Box<AssemblyBlock>),
-    VariableDeclaration(pt::Loc, Vec<usize>, Option<AssemblyExpression>),
-    Assignment(pt::Loc, Vec<AssemblyExpression>, AssemblyExpression),
-    IfBlock(pt::Loc, AssemblyExpression, Box<AssemblyBlock>),
-    Switch {
-        loc: pt::Loc,
-        condition: AssemblyExpression,
-        cases: Vec<CaseBlock>,
-        default: Option<AssemblyBlock>,
-    },
-    For {
-        loc: pt::Loc,
-        init_block: AssemblyBlock,
-        condition: AssemblyExpression,
-        post_block: AssemblyBlock,
-        execution_block: AssemblyBlock,
-    },
-    Leave(pt::Loc),
-    Break(pt::Loc),
-    Continue(pt::Loc),
-}
-
 /// Resolves an assembly statement. Returns a boolean that indicates if the next statement is reachable.
 pub(crate) fn resolve_assembly_statement(
     statement: &pt::AssemblyStatement,
@@ -73,10 +46,7 @@ pub(crate) fn resolve_assembly_statement(
                 symtable,
                 ns,
             );
-            resolved_statements.push((
-                AssemblyStatement::Block(block.loc, Box::new(data.0)),
-                reachable,
-            ));
+            resolved_statements.push((AssemblyStatement::Block(Box::new(data.0)), reachable));
             Ok(data.1)
         }
 

+ 4 - 11
src/sema/assembly/switch.rs

@@ -1,22 +1,14 @@
 use crate::ast::Namespace;
-use crate::sema::assembly::block::{resolve_assembly_block, AssemblyBlock};
-use crate::sema::assembly::expression::{
-    check_type, resolve_assembly_expression, AssemblyExpression,
-};
+use crate::sema::assembly::ast::{AssemblyBlock, AssemblyExpression, AssemblyStatement, CaseBlock};
+use crate::sema::assembly::block::resolve_assembly_block;
+use crate::sema::assembly::expression::{check_type, resolve_assembly_expression};
 use crate::sema::assembly::functions::FunctionsTable;
-use crate::sema::assembly::statements::AssemblyStatement;
 use crate::sema::assembly::types::verify_type_from_expression;
 use crate::sema::expression::ExprContext;
 use crate::sema::symtable::{LoopScopes, Symtable};
 use solang_parser::pt::{AssemblySwitchOptions, CodeLocation};
 use solang_parser::{pt, Diagnostic};
 
-#[derive(Debug, Clone)]
-pub struct CaseBlock {
-    pub condition: AssemblyExpression,
-    pub block: AssemblyBlock,
-}
-
 /// Resolve switch statement
 /// Returns the resolved block and a bool to indicate if the next statement is reachable.
 pub(crate) fn resolve_switch(
@@ -203,6 +195,7 @@ fn resolve_case_block(
 
     Ok((
         CaseBlock {
+            loc: *loc,
             condition: resolved_condition,
             block: case_block.0,
         },

+ 3 - 4
src/sema/assembly/tests/expression.rs

@@ -1,11 +1,10 @@
 #![cfg(test)]
 
 use crate::ast::{Namespace, Symbol, Type, Variable};
+use crate::sema::assembly::ast::{AssemblyExpression, AssemblyFunctionParameter, AssemblySuffix};
 use crate::sema::assembly::builtin::AssemblyBuiltInFunction;
-use crate::sema::assembly::expression::{
-    check_type, resolve_assembly_expression, AssemblyExpression, AssemblySuffix,
-};
-use crate::sema::assembly::functions::{AssemblyFunctionParameter, FunctionsTable};
+use crate::sema::assembly::expression::{check_type, resolve_assembly_expression};
+use crate::sema::assembly::functions::FunctionsTable;
 use crate::sema::assembly::tests::{assert_message_in_diagnostics, parse};
 use crate::sema::expression::ExprContext;
 use crate::sema::symtable::{Symtable, VariableInitializer, VariableUsage};

+ 0 - 125
src/sema/assembly/tests/unused_variables.rs

@@ -1,125 +0,0 @@
-use crate::sema::assembly::tests::{assert_message_in_diagnostics, parse};
-
-#[test]
-fn unused_variables() {
-    let file = r#"
-contract testTypes {
-    function testAsm() public {
-        assembly {
-
-            let a
-            for {let i := 11
-              } lt(i, 10) {i := add(i, 1)
-            stop()
-        } {
-                let x := shr(i, 2)
-                let b := shr(6, 5)
-                    x := mul(x, b)
-                //stop()
-            }
-        }
-    }
-}
-    "#;
-
-    let ns = parse(file);
-    assert!(assert_message_in_diagnostics(
-        &ns.diagnostics,
-        "assembly variable has never been read or assigned"
-    ));
-
-    let file = r#"
-contract testTypes {
-    function testAsm() public {
-        assembly {
-
-            for {let i := 11
-                let c :=5
-              } lt(i, 10) {i := add(i, 1)
-            stop()
-        } {
-                let x := shr(i, 2)
-                let b := shr(6, 5)
-                    x := mul(x, b)
-                //stop()
-            }
-        }
-    }
-}
-    "#;
-
-    let ns = parse(file);
-    assert!(assert_message_in_diagnostics(
-        &ns.diagnostics,
-        "assembly variable has never been read"
-    ));
-}
-
-#[test]
-fn correct_contracts() {
-    let file = r#"
-    contract testTypes {
-    function testAsm() public {
-        assembly {
-
-            for {let i := 11
-                let c :=5
-              } c {i := add(i, 1)
-            stop()
-        } {
-                let x := shr(i, 2)
-                let b := shr(6, 5)
-                    x := mul(x, b)
-                //stop()
-            }
-
-            let x := 0
-            if x {
-                let y := add(1, 2)
-                return(y, 0)
-            }
-
-            let y := 5
-            let z
-            switch y
-            case 0 {z := 4}
-            case 1 {z := add(z, 3)}
-
-        }
-    }
-}    "#;
-
-    let ns = parse(file);
-    for item in &ns.diagnostics {
-        assert!(!item.message.starts_with("assembly variable has never been"));
-    }
-
-    let file = r#"
-    contract testTypes {
-    uint b = 0;
-    struct test {
-        int a;
-        int b;
-    }
-    test tt1;
-    function testAsm(uint256[] calldata vl) public {
-        test storage tt2 = tt1;
-        assembly {
-            let g := vl.length
-            let adr := add(g, tt2.slot)
-            sstore(adr, b.slot)
-        }
-    }
-}    "#;
-
-    let ns = parse(file);
-    assert_eq!(ns.diagnostics.len(), 2);
-    assert!(assert_message_in_diagnostics(
-        &ns.diagnostics,
-        "found contract ‘testTypes’"
-    ));
-    assert!(assert_message_in_diagnostics(
-        &ns.diagnostics,
-        "evm assembly not supported on target solana"
-    ));
-}

+ 1 - 1
src/sema/assembly/types.rs

@@ -1,6 +1,6 @@
 use crate::ast::{Namespace, Type};
 use crate::pt::CodeLocation;
-use crate::sema::assembly::expression::AssemblyExpression;
+use crate::sema::assembly::ast::AssemblyExpression;
 use crate::sema::assembly::functions::FunctionsTable;
 use solang_parser::pt::Identifier;
 use solang_parser::Diagnostic;

+ 1 - 1
src/sema/assembly/unused_variable.rs

@@ -1,5 +1,5 @@
 use crate::ast::Namespace;
-use crate::sema::assembly::expression::AssemblyExpression;
+use crate::sema::assembly::ast::AssemblyExpression;
 use crate::sema::symtable::Symtable;
 
 pub(crate) fn assigned_variable(

+ 1 - 1
src/sema/ast.rs

@@ -3,7 +3,7 @@ use crate::codegen::cfg::ControlFlowGraph;
 pub use crate::parser::diagnostics::*;
 use crate::parser::pt;
 use crate::parser::pt::{CodeLocation, OptionalCodeLocation};
-use crate::sema::assembly::InlineAssembly;
+use crate::sema::assembly::ast::InlineAssembly;
 use crate::Target;
 use num_bigint::BigInt;
 use num_rational::BigRational;

+ 667 - 42
src/sema/dotgraphviz.rs

@@ -1,5 +1,11 @@
 use super::ast::*;
 use crate::parser::pt;
+use crate::sema::assembly::ast::{
+    AssemblyBlock, AssemblyExpression, AssemblyFunction, AssemblyStatement,
+};
+use crate::sema::assembly::builtin::AssemblyBuiltInFunction;
+use crate::sema::symtable::Symtable;
+use solang_parser::pt::Loc;
 
 struct Node {
     name: String,
@@ -501,30 +507,7 @@ impl Dot {
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
             Expression::ConstantVariable(loc, ty, contract, var_no) => {
-                let mut labels = vec![
-                    String::from("constant variable"),
-                    ty.to_string(ns),
-                    ns.loc_to_string(loc),
-                ];
-
-                if let Some(contract) = contract {
-                    labels.insert(
-                        1,
-                        format!(
-                            "{}.{}",
-                            ns.contracts[*contract].name,
-                            ns.contracts[*contract].variables[*var_no].name
-                        ),
-                    );
-                } else {
-                    labels.insert(1, ns.constants[*var_no].name.to_string());
-                }
-
-                self.add_node(
-                    Node::new("constant", labels),
-                    Some(parent),
-                    Some(parent_rel),
-                );
+                self.add_constant_variable(loc, ty, contract, var_no, parent, parent_rel, ns);
             }
             Expression::Variable(loc, ty, var_no) => {
                 let labels = vec![
@@ -540,22 +523,7 @@ impl Dot {
                 );
             }
             Expression::StorageVariable(loc, ty, contract, var_no) => {
-                let labels = vec![
-                    String::from("storage variable"),
-                    format!(
-                        "{}.{}",
-                        ns.contracts[*contract].name,
-                        ns.contracts[*contract].variables[*var_no].name
-                    ),
-                    ty.to_string(ns),
-                    ns.loc_to_string(loc),
-                ];
-
-                self.add_node(
-                    Node::new("storage_var", labels),
-                    Some(parent),
-                    Some(parent_rel),
-                );
+                self.add_storage_variable(loc, ty, contract, var_no, parent, parent_rel, ns);
             }
             Expression::Load(loc, ty, expr) => {
                 let node = self.add_node(
@@ -1562,13 +1530,670 @@ impl Dot {
                     );
                 }
 
-                Statement::Assembly(_) => {
-                    unimplemented!("Assembly block graphviz not ready yet");
+                Statement::Assembly(inline_assembly) => {
+                    let labels = vec![
+                        "inline assembly".to_string(),
+                        ns.loc_to_string(&inline_assembly.loc),
+                    ];
+                    parent = self.add_node(
+                        Node::new("inline_assembly", labels),
+                        Some(parent),
+                        Some(parent_rel),
+                    );
+
+                    let mut local_parent = parent;
+
+                    for n in 0..inline_assembly.functions.len() {
+                        self.add_yul_function(
+                            n,
+                            &inline_assembly.functions,
+                            ns,
+                            local_parent,
+                            format!("func def #{}", n),
+                        );
+                    }
+
+                    local_parent = parent;
+                    for (item_no, item) in inline_assembly.body.iter().enumerate() {
+                        local_parent = self.add_yul_statement(
+                            &item.0,
+                            local_parent,
+                            format!("statement #{}", item_no),
+                            &inline_assembly.functions,
+                            &func.symtable,
+                            ns,
+                        );
+                    }
                 }
             }
             parent_rel = String::from("next");
         }
     }
+
+    fn add_yul_function(
+        &mut self,
+        func_no: usize,
+        avail_functions: &[AssemblyFunction],
+        ns: &Namespace,
+        parent: usize,
+        parent_rel: String,
+    ) {
+        let labels = vec![
+            format!("function definition {}", avail_functions[func_no].name),
+            ns.loc_to_string(&avail_functions[func_no].loc),
+        ];
+
+        let func_node = self.add_node(
+            Node::new("yul_function_definition", labels),
+            Some(parent),
+            Some(parent_rel),
+        );
+
+        let mut local_parent = func_node;
+        for (item_no, item) in (*avail_functions[func_no].params).iter().enumerate() {
+            let labels = vec![
+                format!(
+                    "function parameter {}: {}",
+                    item.ty.to_string(ns),
+                    item.id.name
+                ),
+                ns.loc_to_string(&item.loc),
+            ];
+            local_parent = self.add_node(
+                Node::new("yul_function_parameter", labels),
+                Some(local_parent),
+                Some(format!("parameter #{}", item_no)),
+            );
+        }
+
+        local_parent = func_node;
+        for (item_no, item) in (*avail_functions[func_no].returns).iter().enumerate() {
+            let labels = vec![
+                format!(
+                    "return parameter {}: {}",
+                    item.ty.to_string(ns),
+                    item.id.name
+                ),
+                ns.loc_to_string(&item.loc),
+            ];
+            local_parent = self.add_node(
+                Node::new("yul_function_return", labels),
+                Some(local_parent),
+                Some(format!("return #{}", item_no)),
+            );
+        }
+
+        local_parent = func_node;
+        for (item_no, item) in avail_functions[func_no].body.iter().enumerate() {
+            local_parent = self.add_yul_statement(
+                &item.0,
+                local_parent,
+                format!("statement #{}", item_no),
+                avail_functions,
+                &avail_functions[func_no].symtable,
+                ns,
+            );
+        }
+    }
+
+    fn add_yul_expression(
+        &mut self,
+        expr: &AssemblyExpression,
+        symtable: &Symtable,
+        avail_functions: &[AssemblyFunction],
+        ns: &Namespace,
+        parent: usize,
+        parent_rel: String,
+    ) {
+        match expr {
+            AssemblyExpression::BoolLiteral(loc, value, ty) => {
+                let labels = vec![
+                    format!(
+                        "bool literal: {} of type {}",
+                        if *value { "true" } else { "false" },
+                        ty.to_string(ns)
+                    ),
+                    ns.loc_to_string(loc),
+                ];
+
+                self.add_node(
+                    Node::new("yul_bool_literal", labels),
+                    Some(parent),
+                    Some(parent_rel),
+                );
+            }
+            AssemblyExpression::NumberLiteral(loc, value, ty) => {
+                let labels = vec![
+                    format!("{} literal: {}", ty.to_string(ns), value),
+                    ns.loc_to_string(loc),
+                ];
+
+                self.add_node(
+                    Node::new("yul_number_literal", labels),
+                    Some(parent),
+                    Some(parent_rel),
+                );
+            }
+            AssemblyExpression::StringLiteral(loc, value, ty) => {
+                let labels = vec![
+                    format!("{} literal: {}", ty.to_string(ns), hex::encode(value)),
+                    ns.loc_to_string(loc),
+                ];
+
+                self.add_node(
+                    Node::new("bytes_literal", labels),
+                    Some(parent),
+                    Some(parent_rel),
+                );
+            }
+            AssemblyExpression::AssemblyLocalVariable(loc, ty, var_no) => {
+                let labels = vec![
+                    format!("yul variable: {}", symtable.vars[var_no].id.name),
+                    ty.to_string(ns),
+                    ns.loc_to_string(loc),
+                ];
+                self.add_node(
+                    Node::new("yul_variable", labels),
+                    Some(parent),
+                    Some(parent_rel),
+                );
+            }
+            AssemblyExpression::SolidityLocalVariable(loc, ty, _, var_no) => {
+                let labels = vec![
+                    format!("solidity variable: {}", symtable.vars[var_no].id.name),
+                    ty.to_string(ns),
+                    ns.loc_to_string(loc),
+                ];
+
+                self.add_node(
+                    Node::new("solidity_variable", labels),
+                    Some(parent),
+                    Some(parent_rel),
+                );
+            }
+            AssemblyExpression::ConstantVariable(loc, ty, contract, var_no) => {
+                self.add_constant_variable(loc, ty, contract, var_no, parent, parent_rel, ns);
+            }
+            AssemblyExpression::StorageVariable(loc, ty, contract, var_no) => {
+                self.add_storage_variable(loc, ty, contract, var_no, parent, parent_rel, ns);
+            }
+            AssemblyExpression::BuiltInCall(loc, builtin_ty, args) => {
+                self.add_yul_builtin_call(
+                    loc,
+                    builtin_ty,
+                    args,
+                    parent,
+                    parent_rel,
+                    avail_functions,
+                    symtable,
+                    ns,
+                );
+            }
+            AssemblyExpression::FunctionCall(loc, func_no, args) => {
+                self.add_yul_function_call(
+                    loc,
+                    func_no,
+                    args,
+                    parent,
+                    parent_rel,
+                    avail_functions,
+                    symtable,
+                    ns,
+                );
+            }
+            AssemblyExpression::MemberAccess(loc, member, suffix) => {
+                let labels = vec![
+                    format!("yul member ‘{}‘ access", suffix.to_string()),
+                    ns.loc_to_string(loc),
+                ];
+
+                let node = self.add_node(
+                    Node::new("yul_member_access", labels),
+                    Some(parent),
+                    Some(parent_rel),
+                );
+
+                self.add_yul_expression(
+                    member,
+                    symtable,
+                    avail_functions,
+                    ns,
+                    node,
+                    "parent".to_string(),
+                );
+            }
+        }
+    }
+
+    fn add_constant_variable(
+        &mut self,
+        loc: &Loc,
+        ty: &Type,
+        contract: &Option<usize>,
+        var_no: &usize,
+        parent: usize,
+        parent_rel: String,
+        ns: &Namespace,
+    ) {
+        let mut labels = vec![
+            String::from("constant variable"),
+            ty.to_string(ns),
+            ns.loc_to_string(loc),
+        ];
+
+        if let Some(contract) = contract {
+            labels.insert(
+                1,
+                format!(
+                    "{}.{}",
+                    ns.contracts[*contract].name, ns.contracts[*contract].variables[*var_no].name
+                ),
+            );
+        } else {
+            labels.insert(1, ns.constants[*var_no].name.to_string());
+        }
+
+        self.add_node(
+            Node::new("constant", labels),
+            Some(parent),
+            Some(parent_rel),
+        );
+    }
+
+    fn add_storage_variable(
+        &mut self,
+        loc: &Loc,
+        ty: &Type,
+        contract: &usize,
+        var_no: &usize,
+        parent: usize,
+        parent_rel: String,
+        ns: &Namespace,
+    ) {
+        let labels = vec![
+            String::from("storage variable"),
+            format!(
+                "{}.{}",
+                ns.contracts[*contract].name, ns.contracts[*contract].variables[*var_no].name
+            ),
+            ty.to_string(ns),
+            ns.loc_to_string(loc),
+        ];
+
+        self.add_node(
+            Node::new("storage_var", labels),
+            Some(parent),
+            Some(parent_rel),
+        );
+    }
+
+    fn add_yul_statement(
+        &mut self,
+        statement: &AssemblyStatement,
+        parent: usize,
+        parent_rel: String,
+        avail_functions: &[AssemblyFunction],
+        symtable: &Symtable,
+        ns: &Namespace,
+    ) -> usize {
+        match statement {
+            AssemblyStatement::FunctionCall(loc, func_no, args) => self.add_yul_function_call(
+                loc,
+                func_no,
+                args,
+                parent,
+                parent_rel,
+                avail_functions,
+                symtable,
+                ns,
+            ),
+            AssemblyStatement::BuiltInCall(loc, builtin_ty, args) => self.add_yul_builtin_call(
+                loc,
+                builtin_ty,
+                args,
+                parent,
+                parent_rel,
+                avail_functions,
+                symtable,
+                ns,
+            ),
+            AssemblyStatement::Block(block) => {
+                self.add_yul_block(block, parent, parent_rel, avail_functions, symtable, ns)
+            }
+            AssemblyStatement::VariableDeclaration(loc, declared_vars, initializer) => {
+                let labels = vec![
+                    "yul variable declaration".to_string(),
+                    ns.loc_to_string(loc),
+                ];
+
+                let node = self.add_node(
+                    Node::new("yul_var_decl", labels),
+                    Some(parent),
+                    Some(parent_rel),
+                );
+
+                for (decl_no, item) in declared_vars.iter().enumerate() {
+                    let var = &symtable.vars[item];
+                    self.add_node(
+                        Node::new(
+                            "var_decl_item",
+                            vec![
+                                format!(
+                                    "yul variable declaration {} {}",
+                                    var.ty.to_string(ns),
+                                    var.id.name
+                                ),
+                                ns.loc_to_string(&var.id.loc),
+                            ],
+                        ),
+                        Some(node),
+                        Some(format!("decl item #{}", decl_no)),
+                    );
+                }
+
+                if let Some(init) = initializer {
+                    self.add_yul_expression(
+                        init,
+                        symtable,
+                        avail_functions,
+                        ns,
+                        node,
+                        "init".to_string(),
+                    );
+                }
+
+                node
+            }
+            AssemblyStatement::Assignment(loc, lhs, rhs) => {
+                let labels = vec!["yul assignment".to_string(), ns.loc_to_string(loc)];
+
+                let node = self.add_node(
+                    Node::new("yul_assignment", labels),
+                    Some(parent),
+                    Some(parent_rel),
+                );
+
+                for (item_no, item) in lhs.iter().enumerate() {
+                    self.add_yul_expression(
+                        item,
+                        symtable,
+                        avail_functions,
+                        ns,
+                        node,
+                        format!("rhs #{}", item_no),
+                    );
+                }
+
+                self.add_yul_expression(
+                    rhs,
+                    symtable,
+                    avail_functions,
+                    ns,
+                    node,
+                    "lhs".to_string(),
+                );
+                node
+            }
+            AssemblyStatement::IfBlock(loc, condition, block) => {
+                let labels = vec!["yul if".to_string(), ns.loc_to_string(loc)];
+
+                let node = self.add_node(Node::new("if", labels), Some(parent), Some(parent_rel));
+
+                self.add_yul_expression(
+                    condition,
+                    symtable,
+                    avail_functions,
+                    ns,
+                    node,
+                    "cond".to_string(),
+                );
+                self.add_yul_block(
+                    block,
+                    node,
+                    "if-block".to_string(),
+                    avail_functions,
+                    symtable,
+                    ns,
+                );
+                node
+            }
+            AssemblyStatement::Switch {
+                loc,
+                condition,
+                cases,
+                default,
+            } => {
+                let labels = vec!["yul switch".to_string(), ns.loc_to_string(loc)];
+
+                let node =
+                    self.add_node(Node::new("switch", labels), Some(parent), Some(parent_rel));
+
+                self.add_yul_expression(
+                    condition,
+                    symtable,
+                    avail_functions,
+                    ns,
+                    node,
+                    "cond".to_string(),
+                );
+
+                for (item_no, item) in cases.iter().enumerate() {
+                    let case_block = self.add_node(
+                        Node::new(
+                            "case",
+                            vec!["yul switch case".to_string(), ns.loc_to_string(&item.loc)],
+                        ),
+                        Some(node),
+                        Some(format!("case #{}", item_no)),
+                    );
+                    self.add_yul_expression(
+                        &item.condition,
+                        symtable,
+                        avail_functions,
+                        ns,
+                        case_block,
+                        "case-condition".to_string(),
+                    );
+                    self.add_yul_block(
+                        &item.block,
+                        case_block,
+                        "case block".to_string(),
+                        avail_functions,
+                        symtable,
+                        ns,
+                    );
+                }
+
+                if let Some(default_block) = default {
+                    let default_node = self.add_node(
+                        Node::new(
+                            "default",
+                            vec![
+                                "yul switch default".to_string(),
+                                ns.loc_to_string(&default_block.loc),
+                            ],
+                        ),
+                        Some(node),
+                        Some("default".to_string()),
+                    );
+                    self.add_yul_block(
+                        default_block,
+                        default_node,
+                        "default block".to_string(),
+                        avail_functions,
+                        symtable,
+                        ns,
+                    );
+                }
+                node
+            }
+            AssemblyStatement::For {
+                loc,
+                init_block,
+                condition,
+                post_block,
+                execution_block,
+            } => {
+                let labels = vec!["yul for".to_string(), ns.loc_to_string(loc)];
+
+                let node = self.add_node(Node::new("for", labels), Some(parent), Some(parent_rel));
+
+                self.add_yul_block(
+                    init_block,
+                    node,
+                    "init block".to_string(),
+                    avail_functions,
+                    symtable,
+                    ns,
+                );
+                self.add_yul_expression(
+                    condition,
+                    symtable,
+                    avail_functions,
+                    ns,
+                    node,
+                    "for condition".to_string(),
+                );
+                self.add_yul_block(
+                    post_block,
+                    node,
+                    "post block".to_string(),
+                    avail_functions,
+                    symtable,
+                    ns,
+                );
+                self.add_yul_block(
+                    execution_block,
+                    node,
+                    "execution block".to_string(),
+                    avail_functions,
+                    symtable,
+                    ns,
+                );
+                node
+            }
+            AssemblyStatement::Leave(loc) => {
+                let labels = vec!["leave".to_string(), ns.loc_to_string(loc)];
+                self.add_node(Node::new("leave", labels), Some(parent), Some(parent_rel))
+            }
+            AssemblyStatement::Break(loc) => {
+                let labels = vec!["break".to_string(), ns.loc_to_string(loc)];
+                self.add_node(Node::new("break", labels), Some(parent), Some(parent_rel))
+            }
+            AssemblyStatement::Continue(loc) => {
+                let labels = vec!["continue".to_string(), ns.loc_to_string(loc)];
+                self.add_node(
+                    Node::new("continue", labels),
+                    Some(parent),
+                    Some(parent_rel),
+                )
+            }
+        }
+    }
+
+    fn add_yul_block(
+        &mut self,
+        block: &AssemblyBlock,
+        mut parent: usize,
+        parent_rel: String,
+        avail_functions: &[AssemblyFunction],
+        symtable: &Symtable,
+        ns: &Namespace,
+    ) -> usize {
+        let label = vec!["assembly block".to_string(), ns.loc_to_string(&block.loc)];
+
+        let node = self.add_node(
+            Node::new("assembly_block", label),
+            Some(parent),
+            Some(parent_rel),
+        );
+
+        parent = node;
+        for (statement_no, child_statement) in block.body.iter().enumerate() {
+            parent = self.add_yul_statement(
+                &child_statement.0,
+                parent,
+                format!("statement #{}", statement_no),
+                avail_functions,
+                symtable,
+                ns,
+            );
+        }
+
+        node
+    }
+
+    fn add_yul_function_call(
+        &mut self,
+        loc: &Loc,
+        func_no: &usize,
+        args: &[AssemblyExpression],
+        parent: usize,
+        parent_rel: String,
+        avail_functions: &[AssemblyFunction],
+        symtable: &Symtable,
+        ns: &Namespace,
+    ) -> usize {
+        let labels = vec![
+            format!("yul function call ‘{}‘", avail_functions[*func_no].name),
+            ns.loc_to_string(loc),
+        ];
+
+        let node = self.add_node(
+            Node::new("yul_function_call", labels),
+            Some(parent),
+            Some(parent_rel),
+        );
+
+        for (arg_no, arg) in args.iter().enumerate() {
+            self.add_yul_expression(
+                arg,
+                symtable,
+                avail_functions,
+                ns,
+                node,
+                format!("arg #{}", arg_no),
+            );
+        }
+
+        node
+    }
+
+    fn add_yul_builtin_call(
+        &mut self,
+        loc: &Loc,
+        builtin_ty: &AssemblyBuiltInFunction,
+        args: &[AssemblyExpression],
+        parent: usize,
+        parent_rel: String,
+        avail_functions: &[AssemblyFunction],
+        symtable: &Symtable,
+        ns: &Namespace,
+    ) -> usize {
+        let labels = vec![
+            format!("yul builtin call ‘{}‘", builtin_ty.to_string()),
+            ns.loc_to_string(loc),
+        ];
+
+        let node = self.add_node(
+            Node::new("yul_builtin_call", labels),
+            Some(parent),
+            Some(parent_rel),
+        );
+
+        for (arg_no, arg) in args.iter().enumerate() {
+            self.add_yul_expression(
+                arg,
+                symtable,
+                avail_functions,
+                ns,
+                node,
+                format!("arg #{}", arg_no),
+            );
+        }
+
+        node
+    }
 }
 
 impl Namespace {

+ 152 - 0
tests/contract_testcases/solana/assembly/function_cal_cond.dot

@@ -0,0 +1,152 @@
+strict digraph "tests/contract_testcases/solana/assembly/function_cal_cond.sol" {
+	contract [label="contract testTypes\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:1:1-20"]
+	testAsm [label="function testAsm\ncontract: testTypes\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:2:5-35\nsignature testAsm()\nvisibility public\nmutability pure"]
+	inline_assembly [label="inline assembly\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:3:9-33:10"]
+	yul_function_definition [label="function definition tryThis\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:5:17-13:18"]
+	yul_function_parameter [label="function parameter uint256: b\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:5:34-35"]
+	yul_function_parameter_7 [label="function parameter uint256: a\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:5:37-38"]
+	yul_function_return [label="return parameter uint256: c\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:5:43-44"]
+	yul_assignment [label="yul assignment\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:6:21-35"]
+	yul_variable [label="yul variable: a\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:6:21-22"]
+	yul_builtin_call [label="yul builtin call ‘add‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:6:26-35"]
+	yul_variable_12 [label="yul variable: a\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:6:30-31"]
+	yul_number_literal [label="uint256 literal: 4\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:6:33-34"]
+	if [label="yul if\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:7:21-9:22"]
+	yul_builtin_call_15 [label="yul builtin call ‘gt‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:7:24-32"]
+	yul_variable_16 [label="yul variable: a\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:7:27-28"]
+	yul_number_literal_17 [label="uint256 literal: 5\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:7:30-31"]
+	assembly_block [label="assembly block\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:7:21-9:22"]
+	leave [label="leave\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:8:25-30"]
+	yul_assignment_20 [label="yul assignment\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:10:21-35"]
+	yul_variable_21 [label="yul variable: b\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:10:21-22"]
+	yul_builtin_call_22 [label="yul builtin call ‘add‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:10:26-35"]
+	yul_variable_23 [label="yul variable: a\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:10:30-31"]
+	yul_number_literal_24 [label="uint256 literal: 6\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:10:33-34"]
+	yul_assignment_25 [label="yul assignment\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:11:21-39"]
+	yul_variable_26 [label="yul variable: c\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:11:21-22"]
+	yul_function_call [label="yul function call ‘tryThat‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:11:26-33"]
+	yul_variable_28 [label="yul variable: b\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:11:34-35"]
+	yul_number_literal_29 [label="uint256 literal: 2\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:11:37-38"]
+	yul_builtin_call_30 [label="yul builtin call ‘return‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:12:21-33"]
+	yul_variable_31 [label="yul variable: b\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:12:28-29"]
+	yul_number_literal_32 [label="uint256 literal: 0\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:12:31-32"]
+	yul_function_definition_33 [label="function definition tryThat\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:23:17-30:18"]
+	yul_function_parameter_34 [label="function parameter uint256: b\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:23:34-35"]
+	yul_function_parameter_35 [label="function parameter uint256: a\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:23:37-38"]
+	yul_function_return_36 [label="return parameter uint256: c\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:23:43-44"]
+	yul_assignment_37 [label="yul assignment\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:24:21-35"]
+	yul_variable_38 [label="yul variable: a\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:24:21-22"]
+	yul_builtin_call_39 [label="yul builtin call ‘add‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:24:26-35"]
+	yul_variable_40 [label="yul variable: a\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:24:30-31"]
+	yul_number_literal_41 [label="uint256 literal: 4\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:24:33-34"]
+	if_42 [label="yul if\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:25:21-27:22"]
+	yul_builtin_call_43 [label="yul builtin call ‘gt‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:25:24-32"]
+	yul_variable_44 [label="yul variable: a\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:25:27-28"]
+	yul_number_literal_45 [label="uint256 literal: 5\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:25:30-31"]
+	assembly_block_46 [label="assembly block\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:25:21-27:22"]
+	leave_47 [label="leave\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:26:25-30"]
+	yul_assignment_48 [label="yul assignment\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:28:21-27"]
+	yul_variable_49 [label="yul variable: c\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:28:21-22"]
+	yul_number_literal_50 [label="uint256 literal: 5\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:28:26-27"]
+	yul_builtin_call_51 [label="yul builtin call ‘return‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:29:21-33"]
+	yul_variable_52 [label="yul variable: b\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:29:28-29"]
+	yul_number_literal_53 [label="uint256 literal: 0\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:29:31-32"]
+	yul_function_definition_54 [label="function definition foo\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:16:21-18:22"]
+	yul_function_parameter_55 [label="function parameter uint256: d\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:16:34-35"]
+	yul_function_return_56 [label="return parameter uint256: e\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:16:40-41"]
+	yul_assignment_57 [label="yul assignment\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:17:25-39"]
+	yul_variable_58 [label="yul variable: e\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:17:25-26"]
+	yul_builtin_call_59 [label="yul builtin call ‘shr‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:17:30-39"]
+	yul_variable_60 [label="yul variable: d\nuint256\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:17:34-35"]
+	yul_number_literal_61 [label="uint256 literal: 3\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:17:37-38"]
+	assembly_block_62 [label="assembly block\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:4:13-32:14"]
+	assembly_block_63 [label="assembly block\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:15:17-21:18"]
+	yul_builtin_call_64 [label="yul builtin call ‘revert‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:20:21-50"]
+	yul_function_call_65 [label="yul function call ‘tryThis‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:20:28-35"]
+	yul_function_call_66 [label="yul function call ‘foo‘\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:20:36-39"]
+	yul_number_literal_67 [label="uint256 literal: 3\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:20:40-41"]
+	yul_number_literal_68 [label="uint256 literal: 2\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:20:44-45"]
+	yul_number_literal_69 [label="uint256 literal: 4\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:20:48-49"]
+	yul_var_decl [label="yul variable declaration\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:31:17-27"]
+	var_decl_item [label="yul variable declaration uint256 x\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:31:21-22"]
+	yul_number_literal_72 [label="uint256 literal: 5\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:31:26-27"]
+	diagnostic [label="found contract ‘testTypes’\nlevel Debug\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:1:1-20"]
+	diagnostic_75 [label="evm assembly not supported on target solana\nlevel Error\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:3:9-33:10"]
+	diagnostic_76 [label="unreachable assembly statement\nlevel Warning\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:31:17-27"]
+	diagnostic_77 [label="assembly variable ‘x‘ has never been read\nlevel Warning\ntests/contract_testcases/solana/assembly/function_cal_cond.sol:31:21-22"]
+	contracts -> contract
+	contract -> testAsm [label="function"]
+	testAsm -> inline_assembly [label="body"]
+	inline_assembly -> yul_function_definition [label="func def #0"]
+	yul_function_definition -> yul_function_parameter [label="parameter #0"]
+	yul_function_parameter -> yul_function_parameter_7 [label="parameter #1"]
+	yul_function_definition -> yul_function_return [label="return #0"]
+	yul_function_definition -> yul_assignment [label="statement #0"]
+	yul_assignment -> yul_variable [label="rhs #0"]
+	yul_assignment -> yul_builtin_call [label="lhs"]
+	yul_builtin_call -> yul_variable_12 [label="arg #0"]
+	yul_builtin_call -> yul_number_literal [label="arg #1"]
+	yul_assignment -> if [label="statement #1"]
+	if -> yul_builtin_call_15 [label="cond"]
+	yul_builtin_call_15 -> yul_variable_16 [label="arg #0"]
+	yul_builtin_call_15 -> yul_number_literal_17 [label="arg #1"]
+	if -> assembly_block [label="if-block"]
+	assembly_block -> leave [label="statement #0"]
+	if -> yul_assignment_20 [label="statement #2"]
+	yul_assignment_20 -> yul_variable_21 [label="rhs #0"]
+	yul_assignment_20 -> yul_builtin_call_22 [label="lhs"]
+	yul_builtin_call_22 -> yul_variable_23 [label="arg #0"]
+	yul_builtin_call_22 -> yul_number_literal_24 [label="arg #1"]
+	yul_assignment_20 -> yul_assignment_25 [label="statement #3"]
+	yul_assignment_25 -> yul_variable_26 [label="rhs #0"]
+	yul_assignment_25 -> yul_function_call [label="lhs"]
+	yul_function_call -> yul_variable_28 [label="arg #0"]
+	yul_function_call -> yul_number_literal_29 [label="arg #1"]
+	yul_assignment_25 -> yul_builtin_call_30 [label="statement #4"]
+	yul_builtin_call_30 -> yul_variable_31 [label="arg #0"]
+	yul_builtin_call_30 -> yul_number_literal_32 [label="arg #1"]
+	inline_assembly -> yul_function_definition_33 [label="func def #1"]
+	yul_function_definition_33 -> yul_function_parameter_34 [label="parameter #0"]
+	yul_function_parameter_34 -> yul_function_parameter_35 [label="parameter #1"]
+	yul_function_definition_33 -> yul_function_return_36 [label="return #0"]
+	yul_function_definition_33 -> yul_assignment_37 [label="statement #0"]
+	yul_assignment_37 -> yul_variable_38 [label="rhs #0"]
+	yul_assignment_37 -> yul_builtin_call_39 [label="lhs"]
+	yul_builtin_call_39 -> yul_variable_40 [label="arg #0"]
+	yul_builtin_call_39 -> yul_number_literal_41 [label="arg #1"]
+	yul_assignment_37 -> if_42 [label="statement #1"]
+	if_42 -> yul_builtin_call_43 [label="cond"]
+	yul_builtin_call_43 -> yul_variable_44 [label="arg #0"]
+	yul_builtin_call_43 -> yul_number_literal_45 [label="arg #1"]
+	if_42 -> assembly_block_46 [label="if-block"]
+	assembly_block_46 -> leave_47 [label="statement #0"]
+	if_42 -> yul_assignment_48 [label="statement #2"]
+	yul_assignment_48 -> yul_variable_49 [label="rhs #0"]
+	yul_assignment_48 -> yul_number_literal_50 [label="lhs"]
+	yul_assignment_48 -> yul_builtin_call_51 [label="statement #3"]
+	yul_builtin_call_51 -> yul_variable_52 [label="arg #0"]
+	yul_builtin_call_51 -> yul_number_literal_53 [label="arg #1"]
+	inline_assembly -> yul_function_definition_54 [label="func def #2"]
+	yul_function_definition_54 -> yul_function_parameter_55 [label="parameter #0"]
+	yul_function_definition_54 -> yul_function_return_56 [label="return #0"]
+	yul_function_definition_54 -> yul_assignment_57 [label="statement #0"]
+	yul_assignment_57 -> yul_variable_58 [label="rhs #0"]
+	yul_assignment_57 -> yul_builtin_call_59 [label="lhs"]
+	yul_builtin_call_59 -> yul_variable_60 [label="arg #0"]
+	yul_builtin_call_59 -> yul_number_literal_61 [label="arg #1"]
+	inline_assembly -> assembly_block_62 [label="statement #0"]
+	assembly_block_62 -> assembly_block_63 [label="statement #0"]
+	assembly_block_63 -> yul_builtin_call_64 [label="statement #0"]
+	yul_builtin_call_64 -> yul_function_call_65 [label="arg #0"]
+	yul_function_call_65 -> yul_function_call_66 [label="arg #0"]
+	yul_function_call_66 -> yul_number_literal_67 [label="arg #0"]
+	yul_function_call_65 -> yul_number_literal_68 [label="arg #1"]
+	yul_builtin_call_64 -> yul_number_literal_69 [label="arg #1"]
+	assembly_block_63 -> yul_var_decl [label="statement #1"]
+	yul_var_decl -> var_decl_item [label="decl item #0"]
+	yul_var_decl -> yul_number_literal_72 [label="init"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_75 [label="Error"]
+	diagnostics -> diagnostic_76 [label="Warning"]
+	diagnostics -> diagnostic_77 [label="Warning"]
+}

+ 35 - 0
tests/contract_testcases/solana/assembly/function_cal_cond.sol

@@ -0,0 +1,35 @@
+contract testTypes {
+    function testAsm() public pure {
+        assembly {
+            {
+                function tryThis(b, a) -> c {
+                    a := add(a, 4)
+                    if gt(a, 5) {
+                        leave
+                    }
+                    b := add(a, 6)
+                    c := tryThat(b, 2)
+                    return(b, 0)
+                }
+
+                {
+                    function foo(d) -> e {
+                        e := shr(d, 3)
+                    }
+
+                    revert(tryThis(foo(3), 2), 4)
+                }
+
+                function tryThat(b, a) -> c {
+                    a := add(a, 4)
+                    if gt(a, 5) {
+                        leave
+                    }
+                    c := 5
+                    return(b, 0)
+                }
+                let x := 5
+            }
+        }
+    }
+} 

+ 32 - 0
tests/contract_testcases/solana/assembly/parse.dot

@@ -0,0 +1,32 @@
+strict digraph "tests/contract_testcases/solana/assembly/parse.sol" {
+	contract [label="contract foo\ntests/contract_testcases/solana/assembly/parse.sol:2:9-22"]
+	get [label="function get\ncontract: foo\ntests/contract_testcases/solana/assembly/parse.sol:3:13-51\nsignature get()\nvisibility public\nmutability nonpayable"]
+	returns [label="returns\nbytes4 "]
+	inline_assembly [label="inline assembly\ntests/contract_testcases/solana/assembly/parse.sol:4:17-7:18"]
+	yul_var_decl [label="yul variable declaration\ntests/contract_testcases/solana/assembly/parse.sol:5:21-55"]
+	var_decl_item [label="yul variable declaration uint256 returndata_size\ntests/contract_testcases/solana/assembly/parse.sol:5:25-40"]
+	yul_builtin_call [label="yul builtin call ‘mload‘\ntests/contract_testcases/solana/assembly/parse.sol:5:44-55"]
+	yul_number_literal [label="uint256 literal: 64\ntests/contract_testcases/solana/assembly/parse.sol:5:50-54"]
+	yul_builtin_call_10 [label="yul builtin call ‘revert‘\ntests/contract_testcases/solana/assembly/parse.sol:6:21-59"]
+	yul_builtin_call_11 [label="yul builtin call ‘add‘\ntests/contract_testcases/solana/assembly/parse.sol:6:28-41"]
+	yul_number_literal_12 [label="uint256 literal: 32\ntests/contract_testcases/solana/assembly/parse.sol:6:32-34"]
+	yul_number_literal_13 [label="uint256 literal: 64\ntests/contract_testcases/solana/assembly/parse.sol:6:36-40"]
+	yul_variable [label="yul variable: returndata_size\nuint256\ntests/contract_testcases/solana/assembly/parse.sol:6:43-58"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/solana/assembly/parse.sol:2:9-22"]
+	diagnostic_17 [label="evm assembly not supported on target solana\nlevel Error\ntests/contract_testcases/solana/assembly/parse.sol:4:17-7:18"]
+	contracts -> contract
+	contract -> get [label="function"]
+	get -> returns [label="returns"]
+	get -> inline_assembly [label="body"]
+	inline_assembly -> yul_var_decl [label="statement #0"]
+	yul_var_decl -> var_decl_item [label="decl item #0"]
+	yul_var_decl -> yul_builtin_call [label="init"]
+	yul_builtin_call -> yul_number_literal [label="arg #0"]
+	yul_var_decl -> yul_builtin_call_10 [label="statement #1"]
+	yul_builtin_call_10 -> yul_builtin_call_11 [label="arg #0"]
+	yul_builtin_call_11 -> yul_number_literal_12 [label="arg #0"]
+	yul_builtin_call_11 -> yul_number_literal_13 [label="arg #1"]
+	yul_builtin_call_10 -> yul_variable [label="arg #1"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_17 [label="Error"]
+}

+ 9 - 0
tests/contract_testcases/solana/assembly/parse.sol

@@ -0,0 +1,9 @@
+
+        contract foo {
+            function get() public returns (bytes4) {
+                assembly {
+                    let returndata_size := mload(0x40)
+                    revert(add(32, 0x40), returndata_size)
+                }
+            }
+        }

+ 18 - 0
tests/contract_testcases/solana/assembly/return_in_asm.dot

@@ -0,0 +1,18 @@
+strict digraph "tests/contract_testcases/solana/assembly/return_in_asm.sol" {
+	contract [label="contract Contract\ntests/contract_testcases/solana/assembly/return_in_asm.sol:1:1-19"]
+	node_3 [label="constructor \ncontract: Contract\ntests/contract_testcases/solana/assembly/return_in_asm.sol:2:5-19\nsignature ()\nvisibility public\nmutability nonpayable"]
+	inline_assembly [label="inline assembly\ntests/contract_testcases/solana/assembly/return_in_asm.sol:3:9-5:10"]
+	yul_builtin_call [label="yul builtin call ‘return‘\ntests/contract_testcases/solana/assembly/return_in_asm.sol:4:13-25"]
+	yul_number_literal [label="uint256 literal: 0\ntests/contract_testcases/solana/assembly/return_in_asm.sol:4:20-21"]
+	yul_number_literal_7 [label="uint256 literal: 0\ntests/contract_testcases/solana/assembly/return_in_asm.sol:4:23-24"]
+	diagnostic [label="found contract ‘Contract’\nlevel Debug\ntests/contract_testcases/solana/assembly/return_in_asm.sol:1:1-19"]
+	diagnostic_10 [label="evm assembly not supported on target solana\nlevel Error\ntests/contract_testcases/solana/assembly/return_in_asm.sol:3:9-5:10"]
+	contracts -> contract
+	contract -> node_3 [label="constructor"]
+	node_3 -> inline_assembly [label="body"]
+	inline_assembly -> yul_builtin_call [label="statement #0"]
+	yul_builtin_call -> yul_number_literal [label="arg #0"]
+	yul_builtin_call -> yul_number_literal_7 [label="arg #1"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_10 [label="Error"]
+}

+ 7 - 0
tests/contract_testcases/solana/assembly/return_in_asm.sol

@@ -0,0 +1,7 @@
+contract Contract {
+    constructor() {
+        assembly {
+            return(0, 0)
+        }
+    }
+}

+ 88 - 0
tests/contract_testcases/solana/assembly/yul_switch.dot

@@ -0,0 +1,88 @@
+strict digraph "tests/contract_testcases/solana/assembly/yul_switch.sol" {
+	contract [label="contract testTypes\ntests/contract_testcases/solana/assembly/yul_switch.sol:1:1-20"]
+	var [label="variable b\nvisibility internal\ntests/contract_testcases/solana/assembly/yul_switch.sol:2:5-14"]
+	testAsm [label="function testAsm\ncontract: testTypes\ntests/contract_testcases/solana/assembly/yul_switch.sol:3:5-74\nsignature testAsm(uint128[])\nvisibility public\nmutability pure"]
+	parameters [label="parameters\nuint128[] vl"]
+	returns [label="returns\nuint256 "]
+	var_decl [label="variable decl uint256 y\ntests/contract_testcases/solana/assembly/yul_switch.sol:4:9-22"]
+	number_literal [label="uint256 literal: 0\ntests/contract_testcases/solana/assembly/yul_switch.sol:4:21-22"]
+	inline_assembly [label="inline assembly\ntests/contract_testcases/solana/assembly/yul_switch.sol:5:9-14:10"]
+	switch [label="yul switch\ntests/contract_testcases/solana/assembly/yul_switch.sol:6:13-11:14"]
+	yul_member_access [label="yul member ‘length‘ access\ntests/contract_testcases/solana/assembly/yul_switch.sol:6:20-29"]
+	solidity_variable [label="solidity variable: vl\nuint128[]\ntests/contract_testcases/solana/assembly/yul_switch.sol:6:20-22"]
+	case [label="yul switch case\ntests/contract_testcases/solana/assembly/yul_switch.sol:7:13-41"]
+	yul_number_literal [label="uint256 literal: 1\ntests/contract_testcases/solana/assembly/yul_switch.sol:7:18-19"]
+	assembly_block [label="assembly block\ntests/contract_testcases/solana/assembly/yul_switch.sol:7:13-41"]
+	yul_assignment [label="yul assignment\ntests/contract_testcases/solana/assembly/yul_switch.sol:7:21-40"]
+	solidity_variable_17 [label="solidity variable: y\nuint256\ntests/contract_testcases/solana/assembly/yul_switch.sol:7:21-22"]
+	yul_builtin_call [label="yul builtin call ‘mul‘\ntests/contract_testcases/solana/assembly/yul_switch.sol:7:26-40"]
+	yul_member_access_19 [label="yul member ‘slot‘ access\ntests/contract_testcases/solana/assembly/yul_switch.sol:7:30-36"]
+	storage_var [label="storage variable\ntestTypes.b\nuint256\ntests/contract_testcases/solana/assembly/yul_switch.sol:7:30-31"]
+	yul_number_literal_21 [label="uint256 literal: 2\ntests/contract_testcases/solana/assembly/yul_switch.sol:7:38-39"]
+	case_22 [label="yul switch case\ntests/contract_testcases/solana/assembly/yul_switch.sol:8:13-43"]
+	yul_number_literal_23 [label="uint256 literal: 2\ntests/contract_testcases/solana/assembly/yul_switch.sol:8:18-19"]
+	assembly_block_24 [label="assembly block\ntests/contract_testcases/solana/assembly/yul_switch.sol:8:13-43"]
+	yul_assignment_25 [label="yul assignment\ntests/contract_testcases/solana/assembly/yul_switch.sol:8:21-42"]
+	solidity_variable_26 [label="solidity variable: y\nuint256\ntests/contract_testcases/solana/assembly/yul_switch.sol:8:21-22"]
+	yul_builtin_call_27 [label="yul builtin call ‘shr‘\ntests/contract_testcases/solana/assembly/yul_switch.sol:8:26-42"]
+	yul_member_access_28 [label="yul member ‘offset‘ access\ntests/contract_testcases/solana/assembly/yul_switch.sol:8:30-38"]
+	storage_var_29 [label="storage variable\ntestTypes.b\nuint256\ntests/contract_testcases/solana/assembly/yul_switch.sol:8:30-31"]
+	yul_number_literal_30 [label="uint256 literal: 2\ntests/contract_testcases/solana/assembly/yul_switch.sol:8:40-41"]
+	default [label="yul switch default\ntests/contract_testcases/solana/assembly/yul_switch.sol:9:13-11:14"]
+	assembly_block_32 [label="assembly block\ntests/contract_testcases/solana/assembly/yul_switch.sol:9:13-11:14"]
+	yul_assignment_33 [label="yul assignment\ntests/contract_testcases/solana/assembly/yul_switch.sol:10:17-23"]
+	solidity_variable_34 [label="solidity variable: y\nuint256\ntests/contract_testcases/solana/assembly/yul_switch.sol:10:17-18"]
+	yul_number_literal_35 [label="uint256 literal: 5\ntests/contract_testcases/solana/assembly/yul_switch.sol:10:22-23"]
+	yul_assignment_36 [label="yul assignment\ntests/contract_testcases/solana/assembly/yul_switch.sol:13:13-27"]
+	solidity_variable_37 [label="solidity variable: y\nuint256\ntests/contract_testcases/solana/assembly/yul_switch.sol:13:13-14"]
+	yul_builtin_call_38 [label="yul builtin call ‘sub‘\ntests/contract_testcases/solana/assembly/yul_switch.sol:13:18-27"]
+	solidity_variable_39 [label="solidity variable: y\nuint256\ntests/contract_testcases/solana/assembly/yul_switch.sol:13:22-23"]
+	yul_number_literal_40 [label="uint256 literal: 1\ntests/contract_testcases/solana/assembly/yul_switch.sol:13:25-26"]
+	return [label="return\ntests/contract_testcases/solana/assembly/yul_switch.sol:16:9-17"]
+	variable [label="variable: y\nuint256\ntests/contract_testcases/solana/assembly/yul_switch.sol:16:16-17"]
+	diagnostic [label="found contract ‘testTypes’\nlevel Debug\ntests/contract_testcases/solana/assembly/yul_switch.sol:1:1-20"]
+	diagnostic_45 [label="evm assembly not supported on target solana\nlevel Error\ntests/contract_testcases/solana/assembly/yul_switch.sol:5:9-14:10"]
+	contracts -> contract
+	contract -> var [label="variable"]
+	contract -> testAsm [label="function"]
+	testAsm -> parameters [label="parameters"]
+	testAsm -> returns [label="returns"]
+	testAsm -> var_decl [label="body"]
+	var_decl -> number_literal [label="init"]
+	var_decl -> inline_assembly [label="next"]
+	inline_assembly -> switch [label="statement #0"]
+	switch -> yul_member_access [label="cond"]
+	yul_member_access -> solidity_variable [label="parent"]
+	switch -> case [label="case #0"]
+	case -> yul_number_literal [label="case-condition"]
+	case -> assembly_block [label="case block"]
+	assembly_block -> yul_assignment [label="statement #0"]
+	yul_assignment -> solidity_variable_17 [label="rhs #0"]
+	yul_assignment -> yul_builtin_call [label="lhs"]
+	yul_builtin_call -> yul_member_access_19 [label="arg #0"]
+	yul_member_access_19 -> storage_var [label="parent"]
+	yul_builtin_call -> yul_number_literal_21 [label="arg #1"]
+	switch -> case_22 [label="case #1"]
+	case_22 -> yul_number_literal_23 [label="case-condition"]
+	case_22 -> assembly_block_24 [label="case block"]
+	assembly_block_24 -> yul_assignment_25 [label="statement #0"]
+	yul_assignment_25 -> solidity_variable_26 [label="rhs #0"]
+	yul_assignment_25 -> yul_builtin_call_27 [label="lhs"]
+	yul_builtin_call_27 -> yul_member_access_28 [label="arg #0"]
+	yul_member_access_28 -> storage_var_29 [label="parent"]
+	yul_builtin_call_27 -> yul_number_literal_30 [label="arg #1"]
+	switch -> default [label="default"]
+	default -> assembly_block_32 [label="default block"]
+	assembly_block_32 -> yul_assignment_33 [label="statement #0"]
+	yul_assignment_33 -> solidity_variable_34 [label="rhs #0"]
+	yul_assignment_33 -> yul_number_literal_35 [label="lhs"]
+	switch -> yul_assignment_36 [label="statement #1"]
+	yul_assignment_36 -> solidity_variable_37 [label="rhs #0"]
+	yul_assignment_36 -> yul_builtin_call_38 [label="lhs"]
+	yul_builtin_call_38 -> solidity_variable_39 [label="arg #0"]
+	yul_builtin_call_38 -> yul_number_literal_40 [label="arg #1"]
+	inline_assembly -> return [label="next"]
+	return -> variable [label="expr"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_45 [label="Error"]
+}

+ 18 - 0
tests/contract_testcases/solana/assembly/yul_switch.sol

@@ -0,0 +1,18 @@
+contract testTypes {
+    uint256 b;
+    function testAsm(uint128[] calldata vl) public pure returns (uint256) {
+        uint256 y = 0;
+        assembly {
+            switch vl.length
+            case 1 {y := mul(b.slot, 2)}
+            case 2 {y := shr(b.offset, 2)}
+            default {
+                y := 5
+            }
+
+            y := sub(y, 1)
+        }
+
+        return y;
+    }
+}