From e40c498260a4be0840ed251a78f0992e8ab81b12 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Tue, 10 Sep 2019 13:35:55 +0200 Subject: [PATCH 01/20] Adapting the tests to strict inline assembly. --- test/cmdlineTests/strict_asm_jump/err | 2 +- test/libsolidity/InlineAssembly.cpp | 163 +++--------------- test/libsolidity/SolidityEndToEndTest.cpp | 8 +- test/libsolidity/ViewPureChecker.cpp | 2 +- .../inlineAssembly/function_call_to_label.sol | 13 -- .../inlineAssembly/function_without_call.sol | 2 +- .../invalid/bare_instructions_disallowed.sol | 3 +- .../invalid/jump_disallowed.sol | 2 +- .../invalid/jump_invalid_label.sol | 10 -- .../invalid/label_disallowed.sol | 3 +- .../invalid/leave_items_on_tack.sol | 3 +- .../invalid/literals_on_stack_disallowed.sol | 3 +- .../invalid/no_identifier_assignment.sol | 9 - .../invalid/no_identifier_label.sol | 9 - .../invalid/unbalanced_negative_stack.sol | 3 +- .../invalid/unbalanced_positive_stack.sol | 3 +- .../storage_reference_empty_offset.sol | 4 +- .../storage_reference_empty_slot.sol | 4 +- .../syntaxTests/viewPureChecker/assembly.sol | 4 +- test/libyul/Parser.cpp | 7 - 20 files changed, 45 insertions(+), 212 deletions(-) delete mode 100644 test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol delete mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid/jump_invalid_label.sol delete mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid/no_identifier_assignment.sol delete mode 100644 test/libsolidity/syntaxTests/inlineAssembly/invalid/no_identifier_label.sol diff --git a/test/cmdlineTests/strict_asm_jump/err b/test/cmdlineTests/strict_asm_jump/err index 8463daa82..b4f25866a 100644 --- a/test/cmdlineTests/strict_asm_jump/err +++ b/test/cmdlineTests/strict_asm_jump/err @@ -1,5 +1,5 @@ Warning: Yul and its optimizer are still experimental. Please use the output with care. -Error: Function not found. +Error: Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are disallowed in strict assembly. Use functions, "switch", "if" or "for" statements instead. --> strict_asm_jump/input.sol:1:3: | 1 | { jump(1) } diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 76985f54d..18c21c41c 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -188,22 +188,22 @@ BOOST_AUTO_TEST_CASE(surplus_input) BOOST_AUTO_TEST_CASE(simple_instructions) { - BOOST_CHECK(successParse("{ dup1 dup1 mul dup1 sub pop }")); + BOOST_CHECK(successParse("{ let y := mul(0x10, mul(0x20, mload(0x40)))}")); } BOOST_AUTO_TEST_CASE(selfdestruct) { - BOOST_CHECK(successParse("{ 0x02 selfdestruct }")); + BOOST_CHECK(successParse("{ selfdestruct(0x02) }")); } BOOST_AUTO_TEST_CASE(keywords) { - BOOST_CHECK(successParse("{ 1 2 byte 2 return address pop }")); + BOOST_CHECK(successParse("{ return (byte(1, 2), 2) pop(address()) }")); } BOOST_AUTO_TEST_CASE(constants) { - BOOST_CHECK(successParse("{ 7 8 mul pop }")); + BOOST_CHECK(successParse("{ pop(mul(7, 8)) }")); } BOOST_AUTO_TEST_CASE(vardecl) @@ -237,29 +237,14 @@ BOOST_AUTO_TEST_CASE(vardecl_empty) BOOST_CHECK(successParse("{ let x }")); } -BOOST_AUTO_TEST_CASE(assignment) -{ - BOOST_CHECK(successParse("{ let x := 2 7 8 add =: x }")); -} - -BOOST_AUTO_TEST_CASE(label) -{ - BOOST_CHECK(successParse("{ 7 abc: 8 eq abc jump pop }")); -} - -BOOST_AUTO_TEST_CASE(label_complex) -{ - BOOST_CHECK(successParse("{ 7 abc: 8 eq jump(abc) jumpi(eq(7, 8), abc) pop }")); -} - BOOST_AUTO_TEST_CASE(functional) { - BOOST_CHECK(successParse("{ let x := 2 add(7, mul(6, x)) mul(7, 8) add =: x }")); + BOOST_CHECK(successParse("{ let x := 2 x := add(add(7, mul(6, x)), mul(7, 8)) }")); } BOOST_AUTO_TEST_CASE(functional_partial) { - CHECK_PARSE_ERROR("{ let x := byte }", ParserError, "Expected '(' (instruction \"byte\" expects 2 arguments)"); + CHECK_PARSE_ERROR("{ let x := byte }", ParserError, "Expected '(' but got '}'"); } BOOST_AUTO_TEST_CASE(functional_partial_success) @@ -274,12 +259,12 @@ BOOST_AUTO_TEST_CASE(functional_assignment) BOOST_AUTO_TEST_CASE(functional_assignment_complex) { - BOOST_CHECK(successParse("{ let x := 2 x := add(7, mul(6, x)) mul(7, 8) add }")); + BOOST_CHECK(successParse("{ let x := 2 x := add(add(7, mul(6, x)), mul(7, 8)) }")); } BOOST_AUTO_TEST_CASE(vardecl_complex) { - BOOST_CHECK(successParse("{ let y := 2 let x := add(7, mul(6, y)) add mul(7, 8) }")); + BOOST_CHECK(successParse("{ let y := 2 let x := add(add(7, mul(6, y)), mul(7, 8)) }")); } BOOST_AUTO_TEST_CASE(variable_use_before_decl) @@ -303,7 +288,7 @@ BOOST_AUTO_TEST_CASE(if_statement_scope) BOOST_AUTO_TEST_CASE(if_statement_invalid) { - CHECK_PARSE_ERROR("{ if mload {} }", ParserError, "Expected '(' (instruction \"mload\" expects 1 arguments)"); + CHECK_PARSE_ERROR("{ if mload {} }", ParserError, "Expected '(' but got '{'"); BOOST_CHECK("{ if calldatasize() {}"); CHECK_PARSE_ERROR("{ if mstore(1, 1) {} }", TypeError, "Expected expression to return one item to the stack, but did return 0 items"); CHECK_PARSE_ERROR("{ if 32 let x := 3 }", ParserError, "Expected '{' but got reserved keyword 'let'"); @@ -333,7 +318,7 @@ BOOST_AUTO_TEST_CASE(switch_duplicate_case) BOOST_AUTO_TEST_CASE(switch_invalid_expression) { CHECK_PARSE_ERROR("{ switch {} default {} }", ParserError, "Literal, identifier or instruction expected."); - CHECK_PARSE_ERROR("{ switch mload default {} }", ParserError, "Expected '(' (instruction \"mload\" expects 1 arguments)"); + CHECK_PARSE_ERROR("{ switch mload default {} }", ParserError, "Expected '(' but got reserved keyword 'default'"); CHECK_PARSE_ERROR("{ switch mstore(1, 1) default {} }", TypeError, "Expected expression to return one item to the stack, but did return 0 items"); } @@ -369,7 +354,7 @@ BOOST_AUTO_TEST_CASE(for_invalid_expression) CHECK_PARSE_ERROR("{ for 1 1 {} {} }", ParserError, "Expected '{' but got 'Number'"); CHECK_PARSE_ERROR("{ for {} 1 1 {} }", ParserError, "Expected '{' but got 'Number'"); CHECK_PARSE_ERROR("{ for {} 1 {} 1 }", ParserError, "Expected '{' but got 'Number'"); - CHECK_PARSE_ERROR("{ for {} mload {} {} }", ParserError, "Expected '(' (instruction \"mload\" expects 1 arguments)"); + CHECK_PARSE_ERROR("{ for {} mload {} {} }", ParserError, "Expected '(' but got '{'"); CHECK_PARSE_ERROR("{ for {} mstore(1, 1) {} {} }", TypeError, "Expected expression to return one item to the stack, but did return 0 items"); } @@ -463,7 +448,7 @@ BOOST_AUTO_TEST_CASE(functions_in_parallel_scopes) BOOST_AUTO_TEST_CASE(variable_access_cross_functions) { - CHECK_PARSE_ERROR("{ let x := 2 function g() { x pop } }", DeclarationError, "Identifier not found."); + CHECK_PARSE_ERROR("{ let x := 2 function g() { pop(x) } }", DeclarationError, "Identifier not found."); } BOOST_AUTO_TEST_CASE(invalid_tuple_assignment) @@ -516,46 +501,6 @@ BOOST_AUTO_TEST_CASE(multiple_assignment) BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE(LooseStrictMode) - -BOOST_AUTO_TEST_CASE(no_opcodes_in_strict) -{ - BOOST_CHECK(successParse("{ pop(callvalue) }")); - BOOST_CHECK(successParse("{ callvalue pop }")); - CHECK_STRICT_ERROR("{ pop(callvalue) }", ParserError, "Expected '(' but got ')'"); - CHECK_STRICT_ERROR("{ callvalue pop }", ParserError, "Call or assignment expected"); - SUCCESS_STRICT("{ pop(callvalue()) }"); - BOOST_CHECK(successParse("{ switch callvalue case 0 {} }")); - CHECK_STRICT_ERROR("{ switch callvalue case 0 {} }", ParserError, "Expected '(' but got reserved keyword 'case'"); -} - -BOOST_AUTO_TEST_CASE(no_labels_in_strict) -{ - BOOST_CHECK(successParse("{ a: }")); - CHECK_STRICT_ERROR("{ a: }", ParserError, "Labels are not supported"); -} - -BOOST_AUTO_TEST_CASE(no_stack_assign_in_strict) -{ - BOOST_CHECK(successParse("{ let x 4 =: x }")); - CHECK_STRICT_ERROR("{ let x 4 =: x }", ParserError, "Call or assignment expected."); -} - -BOOST_AUTO_TEST_CASE(no_dup_swap_in_strict) -{ - BOOST_CHECK(successParse("{ swap1 }")); - CHECK_STRICT_ERROR("{ swap1 }", ParserError, "Call or assignment expected."); - BOOST_CHECK(successParse("{ dup1 pop }")); - CHECK_STRICT_ERROR("{ dup1 pop }", ParserError, "Call or assignment expected."); - BOOST_CHECK(successParse("{ swap2 }")); - CHECK_STRICT_ERROR("{ swap2 }", ParserError, "Call or assignment expected."); - BOOST_CHECK(successParse("{ dup2 pop }")); - CHECK_STRICT_ERROR("{ dup2 pop }", ParserError, "Call or assignment expected."); - CHECK_PARSE_ERROR("{ switch dup1 case 0 {} }", ParserError, "Instruction \"dup1\" not allowed in this context"); -} - -BOOST_AUTO_TEST_SUITE_END() - BOOST_AUTO_TEST_SUITE(Printing) BOOST_AUTO_TEST_CASE(print_smoke) @@ -565,12 +510,12 @@ BOOST_AUTO_TEST_CASE(print_smoke) BOOST_AUTO_TEST_CASE(print_instructions) { - parsePrintCompare("{\n 7\n 8\n mul\n dup10\n add\n pop\n}"); + parsePrintCompare("{ pop(7) }"); } BOOST_AUTO_TEST_CASE(print_subblock) { - parsePrintCompare("{\n {\n dup4\n add\n }\n}"); + parsePrintCompare("{ { pop(7) } }"); } BOOST_AUTO_TEST_CASE(print_functional) @@ -578,14 +523,9 @@ BOOST_AUTO_TEST_CASE(print_functional) parsePrintCompare("{ let x := mul(sload(0x12), 7) }"); } -BOOST_AUTO_TEST_CASE(print_label) -{ - parsePrintCompare("{\n loop:\n jump(loop)\n}", true); -} - BOOST_AUTO_TEST_CASE(print_assignments) { - parsePrintCompare("{\n let x := mul(2, 3)\n 7\n =: x\n x := add(1, 2)\n}"); + parsePrintCompare("{\n let x := mul(2, 3)\n pop(7)\n x := add(1, 2)\n}"); } BOOST_AUTO_TEST_CASE(print_multi_assignments) @@ -595,7 +535,7 @@ BOOST_AUTO_TEST_CASE(print_multi_assignments) BOOST_AUTO_TEST_CASE(print_string_literals) { - parsePrintCompare("{\n \"\\n'\\xab\\x95\\\"\"\n pop\n}"); + parsePrintCompare("{ let x := \"\\n'\\xab\\x95\\\"\" }"); } BOOST_AUTO_TEST_CASE(print_string_literal_unicode) @@ -661,39 +601,21 @@ BOOST_AUTO_TEST_CASE(oversize_string_literals) CHECK_ASSEMBLE_ERROR("{ let x := \"123456789012345678901234567890123\" }", TypeError, "String literal too long"); } -BOOST_AUTO_TEST_CASE(assignment_after_tag) -{ - BOOST_CHECK(successParse("{ let x := 1 { 7 tag: =: x } }")); -} - BOOST_AUTO_TEST_CASE(magic_variables) { - CHECK_ASSEMBLE_ERROR("{ this pop }", DeclarationError, "Identifier not found"); - CHECK_ASSEMBLE_ERROR("{ ecrecover pop }", DeclarationError, "Identifier not found"); - BOOST_CHECK(successAssemble("{ let ecrecover := 1 ecrecover pop }")); + CHECK_ASSEMBLE_ERROR("{ pop(this) }", DeclarationError, "Identifier not found"); + CHECK_ASSEMBLE_ERROR("{ pop(ecrecover) }", DeclarationError, "Identifier not found"); + BOOST_CHECK(successAssemble("{ let ecrecover := 1 pop(ecrecover) }")); } BOOST_AUTO_TEST_CASE(stack_variables) { - BOOST_CHECK(successAssemble("{ let y := 3 { 2 { let x := y } pop} }")); -} - -BOOST_AUTO_TEST_CASE(imbalanced_stack) -{ - BOOST_CHECK(successAssemble("{ 1 2 mul pop }", false)); - CHECK_ASSEMBLE_ERROR("{ 1 }", DeclarationError, "Unbalanced stack at the end of a block: 1 surplus item(s)."); - CHECK_ASSEMBLE_ERROR("{ pop }", DeclarationError, "Unbalanced stack at the end of a block: 1 missing item(s)."); - BOOST_CHECK(successAssemble("{ let x := 4 7 add }", false)); -} - -BOOST_AUTO_TEST_CASE(error_tag) -{ - CHECK_ERROR("{ jump(invalidJumpLabel) }", true, DeclarationError, "Identifier not found", true); + BOOST_CHECK(successAssemble("{ let y := 3 { let z := 2 { let x := y } } }")); } BOOST_AUTO_TEST_CASE(designated_invalid_instruction) { - BOOST_CHECK(successAssemble("{ invalid }")); + BOOST_CHECK(successAssemble("{ invalid() }")); } BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_declaration) @@ -701,16 +623,6 @@ BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_declaration) CHECK_ASSEMBLE_ERROR("{ let gas := 1 }", ParserError, "Cannot use builtin"); } -BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_assignment) -{ - CHECK_ASSEMBLE_ERROR("{ 2 =: gas }", ParserError, "Identifier expected, got builtin symbol"); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_functional_assignment) -{ - CHECK_ASSEMBLE_ERROR("{ gas := 2 }", ParserError, "Variable name must precede \":=\""); -} - BOOST_AUTO_TEST_CASE(revert) { BOOST_CHECK(successAssemble("{ revert(0, 0) }")); @@ -772,18 +684,10 @@ BOOST_AUTO_TEST_CASE(large_constant) BOOST_AUTO_TEST_CASE(keccak256) { - BOOST_CHECK(successAssemble("{ 0 0 keccak256 pop }")); BOOST_CHECK(successAssemble("{ pop(keccak256(0, 0)) }")); } BOOST_AUTO_TEST_CASE(returndatasize) -{ - if (!dev::test::Options::get().evmVersion().supportsReturndata()) - return; - BOOST_CHECK(successAssemble("{ let r := returndatasize }")); -} - -BOOST_AUTO_TEST_CASE(returndatasize_functional) { if (!dev::test::Options::get().evmVersion().supportsReturndata()) return; @@ -794,7 +698,7 @@ BOOST_AUTO_TEST_CASE(returndatacopy) { if (!dev::test::Options::get().evmVersion().supportsReturndata()) return; - BOOST_CHECK(successAssemble("{ 64 32 0 returndatacopy }")); + BOOST_CHECK(successAssemble("{ returndatacopy(0, 32, 64) }")); } BOOST_AUTO_TEST_CASE(returndatacopy_functional) @@ -836,27 +740,10 @@ BOOST_AUTO_TEST_CASE(shift_constantinople_warning) CHECK_PARSE_WARNING("{ pop(sar(10, 32)) }", TypeError, "The \"sar\" instruction is only available for Constantinople-compatible VMs"); } -BOOST_AUTO_TEST_CASE(chainid_instanbul_warning) +BOOST_AUTO_TEST_CASE(jump_error) { - if (dev::test::Options::get().evmVersion().hasChainID()) - return; - CHECK_PARSE_WARNING("{ pop(chainid()) }", TypeError, "The \"chainid\" instruction is only available for Istanbul-compatible VMs"); -} - -BOOST_AUTO_TEST_CASE(selfbalance_instanbul_warning) -{ - if (dev::test::Options::get().evmVersion().hasSelfBalance()) - return; - CHECK_PARSE_WARNING("{ pop(selfbalance()) }", TypeError, "The \"selfbalance\" instruction is only available for Istanbul-compatible VMs"); -} - -BOOST_AUTO_TEST_CASE(jump_warning) -{ - CHECK_PARSE_WARNING("{ 1 jump }", Warning, "Jump instructions"); - CHECK_PARSE_WARNING("{ 1 2 jumpi }", Warning, "Jump instructions"); - CHECK_PARSE_WARNING("{ jump(44) }", Warning, "Jump instructions"); - CHECK_PARSE_WARNING("{ jumpi(44, 2) }", Warning, "Jump instructions"); - CHECK_PARSE_WARNING("{ a: }", Warning, "Jump instructions"); + CHECK_PARSE_WARNING("{ jump(44) }", SyntaxError, "Jump instructions and labels are low-level EVM features"); + CHECK_PARSE_WARNING("{ jumpi(44, 2) }", SyntaxError, "Jump instructions and labels are low-level EVM features"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index f9e5f6fc3..dd9ba2d39 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -10274,7 +10274,7 @@ BOOST_AUTO_TEST_CASE(correctly_initialize_memory_array_in_constructor) // Make memory dirty. assembly { for { let i := 0 } lt(i, 64) { i := add(i, 1) } { - mstore(msize, not(0)) + mstore(msize(), not(0)) } } uint16[3] memory c; @@ -12920,7 +12920,7 @@ BOOST_AUTO_TEST_CASE(snark) input[3] = p2.Y; bool success; assembly { - success := call(sub(gas, 2000), 6, 0, input, 0xc0, r, 0x60) + success := call(sub(gas(), 2000), 6, 0, input, 0xc0, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } @@ -12936,7 +12936,7 @@ BOOST_AUTO_TEST_CASE(snark) input[2] = s; bool success; assembly { - success := call(sub(gas, 2000), 7, 0, input, 0x80, r, 0x60) + success := call(sub(gas(), 2000), 7, 0, input, 0x80, r, 0x60) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } @@ -12964,7 +12964,7 @@ BOOST_AUTO_TEST_CASE(snark) uint[1] memory out; bool success; assembly { - success := call(sub(gas, 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + success := call(sub(gas(), 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } } diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index 176a349d3..f1176b865 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(assembly_staticcall) string text = R"( contract C { function i() view public { - assembly { pop(staticcall(gas, 1, 2, 3, 4, 5)) } + assembly { pop(staticcall(gas(), 1, 2, 3, 4, 5)) } } } )"; diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol deleted file mode 100644 index 150fb9385..000000000 --- a/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract C { - function f() public pure { - assembly { - l: - - l() - } - } -} -// ---- -// SyntaxError: (63-64): The use of labels is disallowed. Please use "if", "switch", "for" or function calls instead. -// SyntaxError: (63-64): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. -// TypeError: (73-74): Attempt to call label instead of function. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_without_call.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_without_call.sol index 8557e2fa4..073f3fbcb 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/function_without_call.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/function_without_call.sol @@ -8,4 +8,4 @@ contract C { } } // ---- -// TypeError: (86-87): Function k used without being called. +// ParserError: (92-93): Call or assignment expected. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol index 7315d5d1d..4dd8b76df 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol @@ -7,5 +7,4 @@ contract C { } } // ---- -// SyntaxError: (75-82): The use of non-functional instructions is disallowed. Please use functional notation instead. -// SyntaxError: (95-98): The use of non-functional instructions is disallowed. Please use functional notation instead. +// ParserError: (95-98): Expected '(' but got identifier diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/jump_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/jump_disallowed.sol index 6cb35d6df..302dcaec9 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/jump_disallowed.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/jump_disallowed.sol @@ -6,4 +6,4 @@ contract C { } } // ---- -// SyntaxError: (75-82): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. +// SyntaxError: (75-79): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are disallowed in strict assembly. Use functions, "switch", "if" or "for" statements instead. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/jump_invalid_label.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/jump_invalid_label.sol deleted file mode 100644 index 1ad803869..000000000 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/jump_invalid_label.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract C { - function f() public pure { - assembly { - jump(xy) - } - } -} -// ---- -// DeclarationError: (68-70): Identifier not found. -// SyntaxError: (63-71): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/label_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/label_disallowed.sol index 0d7bacb4f..d3f34d0ec 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/label_disallowed.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/label_disallowed.sol @@ -6,5 +6,4 @@ contract C { } } // ---- -// SyntaxError: (75-80): The use of labels is disallowed. Please use "if", "switch", "for" or function calls instead. -// SyntaxError: (75-80): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. +// ParserError: (80-81): Call or assignment expected. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/leave_items_on_tack.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/leave_items_on_tack.sol index 8538a2a0d..5b410d4b6 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/leave_items_on_tack.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/leave_items_on_tack.sol @@ -6,5 +6,4 @@ contract C { } } // ---- -// SyntaxError: (75-83): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. -// DeclarationError: (61-93): Unbalanced stack at the end of a block: 1 surplus item(s). +// TypeError: (75-83): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/literals_on_stack_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/literals_on_stack_disallowed.sol index 62fe71710..b2649cd8c 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/literals_on_stack_disallowed.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/literals_on_stack_disallowed.sol @@ -6,5 +6,4 @@ contract C { } } // ---- -// SyntaxError: (75-76): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. -// DeclarationError: (61-86): Unbalanced stack at the end of a block: 1 surplus item(s). +// ParserError: (85-86): Call or assignment expected. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/no_identifier_assignment.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/no_identifier_assignment.sol deleted file mode 100644 index 1ec898ea5..000000000 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/no_identifier_assignment.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract C { - function f() public pure { - assembly { - return := 1 - } - } -} -// ---- -// ParserError: (70-72): Variable name must precede ":=" in assignment. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/no_identifier_label.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/no_identifier_label.sol deleted file mode 100644 index 4a1e72c63..000000000 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/no_identifier_label.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract C { - function f() public pure { - assembly { - return : 1 - } - } -} -// ---- -// ParserError: (70-71): Label name must precede ":". diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol index 342afc464..73f4ed76a 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol @@ -6,5 +6,4 @@ contract test { } } // ---- -// SyntaxError: (73-76): The use of non-functional instructions is disallowed. Please use functional notation instead. -// DeclarationError: (59-86): Unbalanced stack at the end of a block: 1 missing item(s). +// ParserError: (85-86): Expected '(' but got '}' diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_positive_stack.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_positive_stack.sol index e9599f4bd..25aad5bcd 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_positive_stack.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_positive_stack.sol @@ -6,5 +6,4 @@ contract test { } } // ---- -// SyntaxError: (73-74): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. -// DeclarationError: (59-84): Unbalanced stack at the end of a block: 1 surplus item(s). +// ParserError: (83-84): Call or assignment expected. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol index ec23a2630..8666889b8 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol @@ -1,9 +1,9 @@ contract C { function f() public pure { assembly { - _offset + let x := _offset } } } // ---- -// DeclarationError: (75-82): In variable names _slot and _offset can only be used as a suffix. +// DeclarationError: (84-91): In variable names _slot and _offset can only be used as a suffix. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol index d493a68a5..05935f19f 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol @@ -1,9 +1,9 @@ contract C { function f() public pure { assembly { - _slot + let x := _slot } } } // ---- -// DeclarationError: (75-80): In variable names _slot and _offset can only be used as a suffix. +// DeclarationError: (84-89): In variable names _slot and _offset can only be used as a suffix. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol index 0a11dc3ae..92b5e4c8b 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/assembly.sol @@ -9,7 +9,7 @@ contract C { assembly { x := 7 } } function g() view public { - assembly { for {} 1 { pop(sload(0)) } { } pop(gas) } + assembly { for {} 1 { pop(sload(0)) } { } pop(gas()) } } function h() view public { assembly { function g() { pop(blockhash(20)) } } @@ -18,6 +18,6 @@ contract C { assembly { pop(call(0, 1, 2, 3, 4, 5, 6)) } } function k() public { - assembly { pop(call(gas, 1, 2, 3, 4, 5, 6)) } + assembly { pop(call(gas(), 1, 2, 3, 4, 5, 6)) } } } diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 899f40f72..575329abe 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -208,11 +208,6 @@ BOOST_AUTO_TEST_CASE(tuple_assignment) BOOST_CHECK(successParse("{ function f() -> a:u256, b:u256, c:u256 {} let x:u256, y:u256, z:u256 := f() }")); } -BOOST_AUTO_TEST_CASE(label) -{ - CHECK_ERROR("{ label: }", ParserError, "Labels are not supported."); -} - BOOST_AUTO_TEST_CASE(instructions) { CHECK_ERROR("{ pop }", ParserError, "Call or assignment expected."); @@ -549,11 +544,9 @@ BOOST_AUTO_TEST_CASE(builtins_parser) SimpleDialect dialect; CHECK_ERROR_DIALECT("{ let builtin := 6 }", ParserError, "Cannot use builtin function name \"builtin\" as identifier name.", dialect); CHECK_ERROR_DIALECT("{ function builtin() {} }", ParserError, "Cannot use builtin function name \"builtin\" as identifier name.", dialect); - CHECK_ERROR_DIALECT("{ builtin := 6 }", ParserError, "Variable name must precede \":=\" in assignment.", dialect); CHECK_ERROR_DIALECT("{ function f(x) { f(builtin) } }", ParserError, "Expected '(' but got ')'", dialect); CHECK_ERROR_DIALECT("{ function f(builtin) {}", ParserError, "Cannot use builtin function name \"builtin\" as identifier name.", dialect); CHECK_ERROR_DIALECT("{ function f() -> builtin {}", ParserError, "Cannot use builtin function name \"builtin\" as identifier name.", dialect); - CHECK_ERROR_DIALECT("{ function g() -> a,b {} builtin, builtin2 := g() }", ParserError, "Variable name must precede \",\" in multiple assignment.", dialect); } BOOST_AUTO_TEST_CASE(builtins_analysis) From 99034abcbfc358508ce4a8c687ce9d972c3d98b9 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Tue, 10 Sep 2019 15:31:18 +0200 Subject: [PATCH 02/20] ChangeLog: Adds entry changing inline assembly to strict mode. --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 7232f3f86..f234fd5b9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,9 +10,9 @@ Breaking changes: * General: New reserved keywords: ``virtual``. * Standard JSON Interface: Add option to disable or choose hash method between IPFS and Swarm for the bytecode metadata. * Syntax: ``push(element)`` for dynamic storage arrays do not return the new length anymore. + * Inline Assembly: Only strict inline assembly is allowed. * Type checker: Resulting type of exponentiation is equal to the type of the base. Also allow signed types for the base. - Language Features: * Allow global enums and structs. * Allow underscores as delimiters in hex strings. From 5a52fa547ed0e3df5699d9ac8da6ad384a6d2fd2 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Tue, 10 Sep 2019 15:32:18 +0200 Subject: [PATCH 03/20] Assembly: Changed parser to use strict assembly mode. --- libsolidity/parsing/Parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 59c76d69a..27374ca0f 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1152,7 +1152,7 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con SourceLocation location{position(), -1, source()}; expectToken(Token::Assembly); - yul::Dialect const& dialect = yul::EVMDialect::looseAssemblyForEVM(m_evmVersion); + yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); if (m_scanner->currentToken() == Token::StringLiteral) { if (m_scanner->currentLiteral() != "evmasm") From 5e8d348f6639cb04db2d80bbbc14cb3d68cca161 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Tue, 10 Sep 2019 10:55:39 +0200 Subject: [PATCH 04/20] Assembly: Remove StackAssignment instruction. --- docs/assembly.rst | 2 -- libsolidity/analysis/ViewPureChecker.cpp | 1 - libyul/AsmAnalysis.cpp | 11 ----------- libyul/AsmAnalysis.h | 1 - libyul/AsmData.h | 2 -- libyul/AsmDataForward.h | 3 +-- libyul/AsmParser.cpp | 17 ----------------- libyul/AsmPrinter.cpp | 7 ------- libyul/AsmPrinter.h | 1 - libyul/AsmScopeFiller.h | 1 - libyul/backends/evm/EVMCodeTransform.cpp | 8 -------- libyul/backends/evm/EVMCodeTransform.h | 1 - libyul/backends/wasm/EWasmCodeTransform.cpp | 6 ------ libyul/backends/wasm/EWasmCodeTransform.h | 1 - libyul/optimiser/ASTCopier.cpp | 6 ------ libyul/optimiser/ASTCopier.h | 2 -- libyul/optimiser/ASTWalker.h | 2 -- libyul/optimiser/SyntacticalEquality.cpp | 5 ----- libyul/optimiser/SyntacticalEquality.h | 1 - 19 files changed, 1 insertion(+), 77 deletions(-) diff --git a/docs/assembly.rst b/docs/assembly.rst index d735b54cd..dc5371699 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -763,7 +763,6 @@ Grammar:: AssemblyExpression | AssemblyLocalDefinition | AssemblyAssignment | - AssemblyStackAssignment | LabelDefinition | AssemblyIf | AssemblySwitch | @@ -780,7 +779,6 @@ Grammar:: AssemblyAssignment = IdentifierOrList ':=' AssemblyExpression IdentifierOrList = Identifier | '(' IdentifierList ')' IdentifierList = Identifier ( ',' Identifier)* - AssemblyStackAssignment = '=:' Identifier LabelDefinition = Identifier ':' AssemblyIf = 'if' AssemblyExpression AssemblyBlock AssemblySwitch = 'switch' AssemblyExpression AssemblyCase* diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 7ead355e1..d7efcc5e4 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -58,7 +58,6 @@ public: { boost::apply_visitor(*this, _expr.expression); } - void operator()(yul::StackAssignment const&) {} void operator()(yul::Assignment const& _assignment) { boost::apply_visitor(*this, *_assignment.value); diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 9c62737d8..b08b884de 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -232,17 +232,6 @@ bool AsmAnalyzer::operator()(ExpressionStatement const& _statement) return success; } -bool AsmAnalyzer::operator()(StackAssignment const& _assignment) -{ - checkLooseFeature( - _assignment.location, - "The use of stack assignment is disallowed. Please use assignment in functional notation instead." - ); - bool success = checkAssignment(_assignment.variableName, size_t(-1)); - m_info.stackHeightInfo[&_assignment] = m_stackHeight; - return success; -} - bool AsmAnalyzer::operator()(Assignment const& _assignment) { solAssert(_assignment.value, ""); diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index facae9187..df30631fe 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -87,7 +87,6 @@ public: bool operator()(FunctionalInstruction const& _functionalInstruction); bool operator()(Label const& _label); bool operator()(ExpressionStatement const&); - bool operator()(StackAssignment const&); bool operator()(Assignment const& _assignment); bool operator()(VariableDeclaration const& _variableDeclaration); bool operator()(FunctionDefinition const& _functionDefinition); diff --git a/libyul/AsmData.h b/libyul/AsmData.h index cedff1106..adfa9331e 100644 --- a/libyul/AsmData.h +++ b/libyul/AsmData.h @@ -51,8 +51,6 @@ struct Literal { langutil::SourceLocation location; LiteralKind kind; YulString struct Identifier { langutil::SourceLocation location; YulString name; }; /// Jump label ("name:") struct Label { langutil::SourceLocation location; YulString name; }; -/// Assignment from stack (":= x", moves stack top into x, potentially multiple slots) -struct StackAssignment { langutil::SourceLocation location; Identifier variableName; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. /// diff --git a/libyul/AsmDataForward.h b/libyul/AsmDataForward.h index d01b1dffa..feb0e0724 100644 --- a/libyul/AsmDataForward.h +++ b/libyul/AsmDataForward.h @@ -30,7 +30,6 @@ namespace yul struct Instruction; struct Literal; struct Label; -struct StackAssignment; struct Identifier; struct Assignment; struct VariableDeclaration; @@ -49,6 +48,6 @@ struct Block; struct TypedName; using Expression = boost::variant; -using Statement = boost::variant; +using Statement = boost::variant; } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index ae3056f21..c8484314a 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -144,23 +144,6 @@ Statement Parser::parseStatement() m_scanner->next(); return stmt; } - case Token::Assign: - { - if (m_dialect.flavour != AsmFlavour::Loose) - break; - StackAssignment assignment = createWithLocation(); - advance(); - expectToken(Token::Colon); - assignment.variableName.location = location(); - assignment.variableName.name = YulString(currentLiteral()); - if (m_dialect.builtin(assignment.variableName.name)) - fatalParserError("Identifier expected, got builtin symbol."); - else if (instructions().count(assignment.variableName.name.str())) - fatalParserError("Identifier expected, got instruction name."); - assignment.location.end = endPosition(); - expectToken(Token::Identifier); - return Statement{move(assignment)}; - } default: break; } diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 71151a0cf..580e8544c 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -120,13 +120,6 @@ string AsmPrinter::operator()(Label const& _label) const return _label.name.str() + ":"; } -string AsmPrinter::operator()(StackAssignment const& _assignment) const -{ - solAssert(!m_yul, ""); - solAssert(!_assignment.variableName.name.empty(), "Invalid variable name."); - return "=: " + (*this)(_assignment.variableName); -} - string AsmPrinter::operator()(Assignment const& _assignment) const { solAssert(_assignment.variableNames.size() >= 1, ""); diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 82fed24f2..7c6bcbc70 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -42,7 +42,6 @@ public: std::string operator()(FunctionalInstruction const& _functionalInstruction) const; std::string operator()(ExpressionStatement const& _expr) const; std::string operator()(Label const& _label) const; - std::string operator()(StackAssignment const& _assignment) const; std::string operator()(Assignment const& _assignment) const; std::string operator()(VariableDeclaration const& _variableDeclaration) const; std::string operator()(FunctionDefinition const& _functionDefinition) const; diff --git a/libyul/AsmScopeFiller.h b/libyul/AsmScopeFiller.h index 220538bb2..8b1807398 100644 --- a/libyul/AsmScopeFiller.h +++ b/libyul/AsmScopeFiller.h @@ -55,7 +55,6 @@ public: bool operator()(FunctionalInstruction const&) { return true; } bool operator()(ExpressionStatement const& _expr); bool operator()(Label const& _label); - bool operator()(StackAssignment const&) { return true; } bool operator()(Assignment const&) { return true; } bool operator()(VariableDeclaration const& _variableDeclaration); bool operator()(FunctionDefinition const& _functionDefinition); diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 9ca079f07..64f26eb1d 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -250,14 +250,6 @@ void CodeTransform::operator()(Assignment const& _assignment) checkStackHeight(&_assignment); } -void CodeTransform::operator()(StackAssignment const& _assignment) -{ - solAssert(!m_allowStackOpt, ""); - m_assembly.setSourceLocation(_assignment.location); - generateAssignment(_assignment.variableName); - checkStackHeight(&_assignment); -} - void CodeTransform::operator()(ExpressionStatement const& _statement) { m_assembly.setSourceLocation(_statement.location); diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index 866322d2d..715aa28ee 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -178,7 +178,6 @@ public: void operator()(FunctionCall const&); void operator()(ExpressionStatement const& _statement); void operator()(Label const& _label); - void operator()(StackAssignment const& _assignment); void operator()(Assignment const& _assignment); void operator()(VariableDeclaration const& _varDecl); void operator()(If const& _if); diff --git a/libyul/backends/wasm/EWasmCodeTransform.cpp b/libyul/backends/wasm/EWasmCodeTransform.cpp index f9e28e94a..de089df36 100644 --- a/libyul/backends/wasm/EWasmCodeTransform.cpp +++ b/libyul/backends/wasm/EWasmCodeTransform.cpp @@ -108,12 +108,6 @@ wasm::Expression EWasmCodeTransform::operator()(Assignment const& _assignment) return generateMultiAssignment(move(variableNames), visit(*_assignment.value)); } -wasm::Expression EWasmCodeTransform::operator()(StackAssignment const&) -{ - yulAssert(false, ""); - return {}; -} - wasm::Expression EWasmCodeTransform::operator()(ExpressionStatement const& _statement) { return visitReturnByValue(_statement.expression); diff --git a/libyul/backends/wasm/EWasmCodeTransform.h b/libyul/backends/wasm/EWasmCodeTransform.h index bbe0e1b69..c20ef89ea 100644 --- a/libyul/backends/wasm/EWasmCodeTransform.h +++ b/libyul/backends/wasm/EWasmCodeTransform.h @@ -45,7 +45,6 @@ public: wasm::Expression operator()(yul::FunctionCall const&); wasm::Expression operator()(yul::ExpressionStatement const& _statement); wasm::Expression operator()(yul::Label const& _label); - wasm::Expression operator()(yul::StackAssignment const& _assignment); wasm::Expression operator()(yul::Assignment const& _assignment); wasm::Expression operator()(yul::VariableDeclaration const& _varDecl); wasm::Expression operator()(yul::If const& _if); diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index efe3ff854..085efe6c3 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -59,12 +59,6 @@ Statement ASTCopier::operator()(Assignment const& _assignment) }; } -Statement ASTCopier::operator()(StackAssignment const&) -{ - assertThrow(false, OptimizerException, "Invalid operation."); - return {}; -} - Statement ASTCopier::operator()(Label const&) { assertThrow(false, OptimizerException, "Invalid operation."); diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index b2e0a383a..2ba9727a5 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -51,7 +51,6 @@ public: virtual Statement operator()(ExpressionStatement const& _statement) = 0; virtual Statement operator()(Instruction const& _instruction) = 0; virtual Statement operator()(Label const& _label) = 0; - virtual Statement operator()(StackAssignment const& _assignment) = 0; virtual Statement operator()(Assignment const& _assignment) = 0; virtual Statement operator()(VariableDeclaration const& _varDecl) = 0; virtual Statement operator()(If const& _if) = 0; @@ -78,7 +77,6 @@ public: Expression operator()(FunctionCall const&) override; Statement operator()(ExpressionStatement const& _statement) override; Statement operator()(Label const& _label) override; - Statement operator()(StackAssignment const& _assignment) override; Statement operator()(Assignment const& _assignment) override; Statement operator()(VariableDeclaration const& _varDecl) override; Statement operator()(If const& _if) override; diff --git a/libyul/optimiser/ASTWalker.h b/libyul/optimiser/ASTWalker.h index a1f244795..4e4968556 100644 --- a/libyul/optimiser/ASTWalker.h +++ b/libyul/optimiser/ASTWalker.h @@ -49,7 +49,6 @@ public: virtual void operator()(FunctionCall const& _funCall); virtual void operator()(ExpressionStatement const& _statement); virtual void operator()(Label const&) { assertThrow(false, OptimizerException, ""); } - virtual void operator()(StackAssignment const&) { assertThrow(false, OptimizerException, ""); } virtual void operator()(Assignment const& _assignment); virtual void operator()(VariableDeclaration const& _varDecl); virtual void operator()(If const& _if); @@ -86,7 +85,6 @@ public: virtual void operator()(FunctionCall& _funCall); virtual void operator()(ExpressionStatement& _statement); virtual void operator()(Label&) { assertThrow(false, OptimizerException, ""); } - virtual void operator()(StackAssignment&) { assertThrow(false, OptimizerException, ""); } virtual void operator()(Assignment& _assignment); virtual void operator()(VariableDeclaration& _varDecl); virtual void operator()(If& _if); diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index 9e425b17e..e3bd8bf4f 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -169,11 +169,6 @@ bool SyntacticallyEqual::statementEqual(Label const&, Label const&) assertThrow(false, OptimizerException, ""); } -bool SyntacticallyEqual::statementEqual(StackAssignment const&, StackAssignment const&) -{ - assertThrow(false, OptimizerException, ""); -} - bool SyntacticallyEqual::statementEqual(Block const& _lhs, Block const& _rhs) { return containerEqual(_lhs.statements, _rhs.statements, [this](Statement const& _lhsStmt, Statement const& _rhsStmt) -> bool { diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index c5e722c74..117ce54a9 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -61,7 +61,6 @@ public: private: bool statementEqual(Instruction const& _lhs, Instruction const& _rhs); bool statementEqual(Label const& _lhs, Label const& _rhs); - bool statementEqual(StackAssignment const& _lhs, StackAssignment const& _rhs); bool visitDeclaration(TypedName const& _lhs, TypedName const& _rhs); From e23998fc6ed1ee832d72a450f0a5d602a504a479 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Tue, 10 Sep 2019 11:15:21 +0200 Subject: [PATCH 05/20] Assembly: Remove Label instruction. --- docs/assembly.rst | 2 -- libsolidity/analysis/ViewPureChecker.cpp | 1 - libyul/AsmAnalysis.cpp | 12 ------------ libyul/AsmAnalysis.h | 1 - libyul/AsmData.h | 2 -- libyul/AsmDataForward.h | 2 +- libyul/AsmParser.cpp | 17 ----------------- libyul/AsmPrinter.cpp | 7 ------- libyul/AsmPrinter.h | 1 - libyul/AsmScopeFiller.cpp | 14 -------------- libyul/AsmScopeFiller.h | 1 - libyul/backends/evm/EVMCodeTransform.cpp | 11 ----------- libyul/backends/evm/EVMCodeTransform.h | 1 - libyul/backends/wasm/EWasmCodeTransform.cpp | 6 ------ libyul/backends/wasm/EWasmCodeTransform.h | 1 - libyul/optimiser/ASTCopier.cpp | 6 ------ libyul/optimiser/ASTCopier.h | 2 -- libyul/optimiser/ASTWalker.h | 2 -- libyul/optimiser/SyntacticalEquality.cpp | 5 ----- libyul/optimiser/SyntacticalEquality.h | 1 - 20 files changed, 1 insertion(+), 94 deletions(-) diff --git a/docs/assembly.rst b/docs/assembly.rst index dc5371699..6eaa7d37b 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -763,7 +763,6 @@ Grammar:: AssemblyExpression | AssemblyLocalDefinition | AssemblyAssignment | - LabelDefinition | AssemblyIf | AssemblySwitch | AssemblyFunctionDefinition | @@ -779,7 +778,6 @@ Grammar:: AssemblyAssignment = IdentifierOrList ':=' AssemblyExpression IdentifierOrList = Identifier | '(' IdentifierList ')' IdentifierList = Identifier ( ',' Identifier)* - LabelDefinition = Identifier ':' AssemblyIf = 'if' AssemblyExpression AssemblyBlock AssemblySwitch = 'switch' AssemblyExpression AssemblyCase* ( 'default' AssemblyBlock )? diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index d7efcc5e4..6d644aa4d 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -41,7 +41,6 @@ public: m_dialect(_dialect), m_reportMutability(_reportMutability) {} - void operator()(yul::Label const&) { } void operator()(yul::Instruction const& _instruction) { checkInstruction(_instruction.location, _instruction.instruction); diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index b08b884de..3135693b5 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -87,18 +87,6 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, return analysisInfo; } -bool AsmAnalyzer::operator()(Label const& _label) -{ - solAssert(!_label.name.empty(), ""); - checkLooseFeature( - _label.location, - "The use of labels is disallowed. Please use \"if\", \"switch\", \"for\" or function calls instead." - ); - m_info.stackHeightInfo[&_label] = m_stackHeight; - warnOnInstructions(dev::eth::Instruction::JUMPDEST, _label.location); - return true; -} - bool AsmAnalyzer::operator()(yul::Instruction const& _instruction) { checkLooseFeature( diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index df30631fe..db11b47bd 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -85,7 +85,6 @@ public: bool operator()(Literal const& _literal); bool operator()(Identifier const&); bool operator()(FunctionalInstruction const& _functionalInstruction); - bool operator()(Label const& _label); bool operator()(ExpressionStatement const&); bool operator()(Assignment const& _assignment); bool operator()(VariableDeclaration const& _variableDeclaration); diff --git a/libyul/AsmData.h b/libyul/AsmData.h index adfa9331e..e29bf8ef6 100644 --- a/libyul/AsmData.h +++ b/libyul/AsmData.h @@ -49,8 +49,6 @@ enum class LiteralKind { Number, Boolean, String }; struct Literal { langutil::SourceLocation location; LiteralKind kind; YulString value; Type type; }; /// External / internal identifier or label reference struct Identifier { langutil::SourceLocation location; YulString name; }; -/// Jump label ("name:") -struct Label { langutil::SourceLocation location; YulString name; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. /// diff --git a/libyul/AsmDataForward.h b/libyul/AsmDataForward.h index feb0e0724..abfbf4a47 100644 --- a/libyul/AsmDataForward.h +++ b/libyul/AsmDataForward.h @@ -48,6 +48,6 @@ struct Block; struct TypedName; using Expression = boost::variant; -using Statement = boost::variant; +using Statement = boost::variant; } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index c8484314a..370a39c56 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -205,23 +205,6 @@ Statement Parser::parseStatement() return Statement{std::move(assignment)}; } - case Token::Colon: - { - if (elementary.type() != typeid(Identifier)) - fatalParserError("Label name must precede \":\"."); - - Identifier const& identifier = boost::get(elementary); - - advance(); - - // label - if (m_dialect.flavour != AsmFlavour::Loose) - fatalParserError("Labels are not supported."); - - Label label = createWithLocation