Преглед изворни кода

Merge pull request #841 from seanyoung/assembly-flag

Parse assembly statement flags
Sean Young пре 3 година
родитељ
комит
55f4ddafe3

+ 1 - 0
solang-parser/src/pt.rs

@@ -644,6 +644,7 @@ pub enum Statement {
     Assembly {
         loc: Loc,
         dialect: Option<StringLiteral>,
+        flags: Option<Vec<StringLiteral>>,
         block: YulBlock,
     },
     Args(Loc, Vec<NamedArgument>),

+ 6 - 1
solang-parser/src/solidity.lalrpop

@@ -721,10 +721,11 @@ NonIfStatement: Statement = {
     <l:@L> "unchecked" "{" <statements:Statement*> "}" <r:@R> => {
         Statement::Block { loc: Loc::File(file_no, l, r), unchecked: true, statements }
     },
-    <l:@L> "assembly" <dialect:StringLiteral?> <block:YulBlock> <r:@R> => {
+    <l:@L> "assembly" <dialect:StringLiteral?> <flags:AssemblyFlags?> <block:YulBlock> <r:@R> => {
         Statement::Assembly {
             loc: Loc::File(file_no, l, r),
             dialect: dialect.map(|dialect| dialect.to_owned()),
+            flags: flags.map(|flag| flag.to_owned()),
             block
         }
     },
@@ -758,6 +759,10 @@ NonIfStatement: Statement = {
     },
 }
 
+AssemblyFlags: Vec<StringLiteral> = {
+    "(" <CommaOne<StringLiteral>> ")" => <>,
+}
+
 YulIdentifier: Identifier = {
     <l:@L> <n:identifier> <r:@R> => Identifier{loc: Loc::File(file_no, l, r), name: n.to_string()},
     <l:@L> "return" <r:@R> => Identifier{loc: Loc::File(file_no, l, r), name: "return".to_string()},

+ 2 - 0
solang-parser/src/test.rs

@@ -719,6 +719,7 @@ fn test_assembly_parser() {
                             loc: Loc::File(0, 63, 71),
                             string: "evmasm".to_string(),
                         }),
+                        flags: None,
                     },
                     Statement::Assembly {
                         loc: Loc::File(0, 758, 1027),
@@ -840,6 +841,7 @@ fn test_assembly_parser() {
                             ))],
                         },
                         dialect: None,
+                        flags: None,
                     },
                 ],
             }),

+ 10 - 0
src/sema/statements.rs

@@ -823,6 +823,7 @@ fn statement(
         pt::Statement::Assembly {
             loc,
             dialect,
+            flags,
             block,
         } => {
             if dialect.is_some() && dialect.as_ref().unwrap().string != "evmasm" {
@@ -833,6 +834,15 @@ fn statement(
                 return Err(());
             }
 
+            if let Some(flags) = flags {
+                for flag in flags {
+                    ns.diagnostics.push(Diagnostic::error(
+                        flag.loc,
+                        format!("flag '{}' not supported", flag.string),
+                    ));
+                }
+            }
+
             let resolved_asm =
                 resolve_inline_assembly(loc, &block.statements, context, symtable, ns);
             res.push(Statement::Assembly(resolved_asm.0, resolved_asm.1));

+ 1 - 1
tests/contract_testcases/solana/yul/return_in_asm.dot

@@ -6,7 +6,7 @@ strict digraph "tests/contract_testcases/solana/yul/return_in_asm.sol" {
 	yul_number_literal [label="uint256 literal: 0\ntests/contract_testcases/solana/yul/return_in_asm.sol:4:20-21"]
 	yul_number_literal_7 [label="uint256 literal: 0\ntests/contract_testcases/solana/yul/return_in_asm.sol:4:23-24"]
 	diagnostic [label="found contract 'Contract'\nlevel Debug\ntests/contract_testcases/solana/yul/return_in_asm.sol:1:1-19"]
-	diagnostic_10 [label="inline assembly is not yet supported\nlevel Error\ntests/contract_testcases/solana/yul/return_in_asm.sol:3:9-5:10"]
+	diagnostic_10 [label="flag 'memory-safe' not supported\nlevel Error\ntests/contract_testcases/solana/yul/return_in_asm.sol:3:19-32"]
 	contracts -> contract
 	contract -> node_3 [label="constructor"]
 	node_3 -> inline_assembly [label="body"]

+ 1 - 1
tests/contract_testcases/solana/yul/return_in_asm.sol

@@ -1,6 +1,6 @@
 contract Contract {
     constructor() {
-        assembly {
+        assembly ("memory-safe") {
             return(0, 0)
         }
     }

+ 5 - 1
tests/contract_testcases/substrate/yul/unreachable_after_asm.dot

@@ -4,11 +4,15 @@ strict digraph "tests/contract_testcases/substrate/yul/unreachable_after_asm.sol
 	testAsm [label="function testAsm\ncontract: testTypes\ntests/contract_testcases/substrate/yul/unreachable_after_asm.sol:3:5-51\nsignature testAsm(uint128[])\nvisibility public\nmutability nonpayable"]
 	parameters [label="parameters\nuint128[] vl"]
 	diagnostic [label="found contract 'testTypes'\nlevel Debug\ntests/contract_testcases/substrate/yul/unreachable_after_asm.sol:1:1-20"]
-	diagnostic_7 [label="unreachable statement\nlevel Error\ntests/contract_testcases/substrate/yul/unreachable_after_asm.sol:17:9-19:10"]
+	diagnostic_7 [label="flag 'memory-safe' not supported\nlevel Error\ntests/contract_testcases/substrate/yul/unreachable_after_asm.sol:5:19-32"]
+	diagnostic_8 [label="flag 'meh' not supported\nlevel Error\ntests/contract_testcases/substrate/yul/unreachable_after_asm.sol:5:34-39"]
+	diagnostic_9 [label="unreachable statement\nlevel Error\ntests/contract_testcases/substrate/yul/unreachable_after_asm.sol:17:9-19:10"]
 	contracts -> contract
 	contract -> var [label="variable"]
 	contract -> testAsm [label="function"]
 	testAsm -> parameters [label="parameters"]
 	diagnostics -> diagnostic [label="Debug"]
 	diagnostics -> diagnostic_7 [label="Error"]
+	diagnostics -> diagnostic_8 [label="Error"]
+	diagnostics -> diagnostic_9 [label="Error"]
 }

+ 2 - 2
tests/contract_testcases/substrate/yul/unreachable_after_asm.sol

@@ -2,7 +2,7 @@ contract testTypes {
     uint256 b;
     function testAsm(uint128[] calldata vl) public {
         uint256 y = 0;
-        assembly {
+        assembly ("memory-safe", "meh") {
             switch vl.length
             case 1 {y := mul(b.slot, 2)}
             case 2 {y := shr(b.offset, 2)}
@@ -18,4 +18,4 @@ contract testTypes {
             b = 5;
         }
     }
-} 
+}