diff options
Diffstat (limited to 'test')
49 files changed, 874 insertions, 110 deletions
diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json index 0f30e8e8..c8b71628 100644 --- a/test/libsolidity/ASTJSON/address_payable.json +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -277,7 +277,7 @@ "name" : "this", "nodeType" : "Identifier", "overloadedDeclarations" : [], - "referencedDeclaration" : 65, + "referencedDeclaration" : 66, "src" : "217:4:1", "typeDescriptions" : { diff --git a/test/libsolidity/ASTJSON/address_payable_legacy.json b/test/libsolidity/ASTJSON/address_payable_legacy.json index dd8a5582..8abebce0 100644 --- a/test/libsolidity/ASTJSON/address_payable_legacy.json +++ b/test/libsolidity/ASTJSON/address_payable_legacy.json @@ -424,7 +424,7 @@ [ null ], - "referencedDeclaration" : 65, + "referencedDeclaration" : 66, "type" : "contract C", "value" : "this" }, diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index baa9bff1..b5a1797b 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -46,6 +46,7 @@ namespace dev { namespace solidity { +class Contract; namespace test { @@ -84,7 +85,7 @@ eth::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) { Compiler compiler(dev::test::Options::get().evmVersion()); - compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}, bytes()); + compiler.compileContract(*contract, map<ContractDefinition const*, shared_ptr<Compiler const>>{}, bytes()); return compiler.runtimeAssemblyItems(); } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 8d219d16..38be5ae7 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -14234,6 +14234,113 @@ BOOST_AUTO_TEST_CASE(base_access_to_function_type_variables) ABI_CHECK(callContractFunction("h()"), encodeArgs(2)); } +BOOST_AUTO_TEST_CASE(code_access) +{ + char const* sourceCode = R"( + contract C { + function lengths() public pure returns (bool) { + uint crLen = type(D).creationCode.length; + uint runLen = type(D).runtimeCode.length; + require(runLen < crLen); + require(crLen >= 0x20); + require(runLen >= 0x20); + return true; + } + function creation() public pure returns (bytes memory) { + return type(D).creationCode; + } + function runtime() public pure returns (bytes memory) { + return type(D).runtimeCode; + } + function runtimeAllocCheck() public pure returns (bytes memory) { + uint[] memory a = new uint[](2); + bytes memory c = type(D).runtimeCode; + uint[] memory b = new uint[](2); + a[0] = 0x1111; + a[1] = 0x2222; + b[0] = 0x3333; + b[1] = 0x4444; + return c; + } + } + contract D { + function f() public pure returns (uint) { return 7; } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("lengths()"), encodeArgs(true)); + bytes codeCreation = callContractFunction("creation()"); + bytes codeRuntime1 = callContractFunction("runtime()"); + bytes codeRuntime2 = callContractFunction("runtimeAllocCheck()"); + ABI_CHECK(codeRuntime1, codeRuntime2); +} + +BOOST_AUTO_TEST_CASE(code_access_create) +{ + char const* sourceCode = R"( + contract C { + function test() public returns (uint) { + bytes memory c = type(D).creationCode; + D d; + assembly { + d := create(0, add(c, 0x20), mload(c)) + } + return d.f(); + } + } + contract D { + uint x; + constructor() public { x = 7; } + function f() public view returns (uint) { return x; } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("test()"), encodeArgs(7)); +} + +BOOST_AUTO_TEST_CASE(code_access_content) +{ + char const* sourceCode = R"( + contract C { + function testRuntime() public returns (bool) { + D d = new D(); + bytes32 runtimeHash = keccak256(type(D).runtimeCode); + bytes32 otherHash; + uint size; + assembly { + size := extcodesize(d) + extcodecopy(d, mload(0x40), 0, size) + otherHash := keccak256(mload(0x40), size) + } + require(size == type(D).runtimeCode.length); + require(runtimeHash == otherHash); + return true; + } + function testCreation() public returns (bool) { + D d = new D(); + bytes32 creationHash = keccak256(type(D).creationCode); + require(creationHash == d.x()); + return true; + } + } + contract D { + bytes32 public x; + constructor() public { + bytes32 codeHash; + assembly { + let size := codesize() + codecopy(mload(0x40), 0, size) + codeHash := keccak256(mload(0x40), size) + } + x = codeHash; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("testRuntime()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("testCreation()"), encodeArgs(true)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index a33c6134..413a8c9c 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -539,7 +539,6 @@ BOOST_AUTO_TEST_CASE(keyword_is_reserved) "supports", "switch", "try", - "type", "typedef", "typeof", "unchecked" diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol new file mode 100644 index 00000000..e90443e1 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccess.sol @@ -0,0 +1,12 @@ +contract Test { + function creationOther() public pure returns (bytes memory) { + return type(Other).creationCode; + } + function runtimeOther() public pure returns (bytes memory) { + return type(Other).runtimeCode; + } +} +contract Other { + function f(uint) public pure returns (uint) {} +} +// ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol new file mode 100644 index 00000000..bae137c5 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractCreation.sol @@ -0,0 +1,10 @@ +contract Test { + function creationOther() public pure returns (bytes memory) { + return type(Other).creationCode; + } +} +contract Other { + function f(uint) public returns (uint); +} +// ---- +// TypeError: (97-121): Member "creationCode" not found or not visible after argument-dependent lookup in type(contract Other). diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol new file mode 100644 index 00000000..186d2714 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessAbstractRuntime.sol @@ -0,0 +1,10 @@ +contract Test { + function runtime() public pure returns (bytes memory) { + return type(Other).runtimeCode; + } +} +contract Other { + function f(uint) public returns (uint); +} +// ---- +// TypeError: (91-114): Member "runtimeCode" not found or not visible after argument-dependent lookup in type(contract Other). diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol new file mode 100644 index 00000000..33dbfd7c --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessBase.sol @@ -0,0 +1,22 @@ +contract Base { + function f() public pure returns (uint) {} +} +contract Test is Base { + function creation() public pure returns (bytes memory) { + return type(Test).creationCode; + } + function runtime() public pure returns (bytes memory) { + return type(Test).runtimeCode; + } + function creationBase() public pure returns (bytes memory) { + return type(Base).creationCode; + } + function runtimeBase() public pure returns (bytes memory) { + return type(Base).runtimeCode; + } +} +// ---- +// TypeError: (165-188): Circular reference for contract code access. +// TypeError: (271-293): Circular reference for contract code access. +// TypeError: (381-404): Circular reference for contract code access. +// TypeError: (491-513): Circular reference for contract code access. diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol new file mode 100644 index 00000000..d5723df6 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessCyclic.sol @@ -0,0 +1,12 @@ +contract A { + function f() public pure { + type(B).runtimeCode; + } +} +contract B { + function f() public pure { + type(A).runtimeCode; + } +} +// ---- +// TypeError: (133-152): Circular reference for contract code access. diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol new file mode 100644 index 00000000..cda5d5c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessIsConstant.sol @@ -0,0 +1,7 @@ +contract Test { + bytes constant c = type(B).creationCode; + bytes constant r = type(B).runtimeCode; + +} +contract B { function f() public pure {} } +// ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol b/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol new file mode 100644 index 00000000..f746dc35 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/codeAccessLibrary.sol @@ -0,0 +1,12 @@ +contract Test { + function creationOther() public pure returns (bytes memory) { + return type(Library).creationCode; + } + function runtime() public pure returns (bytes memory) { + return type(Library).runtimeCode; + } +} +contract Library { + function f(uint) public pure returns (uint) {} +} +// ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol b/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol new file mode 100644 index 00000000..022e4d6f --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/codeIsNoLValue.sol @@ -0,0 +1,10 @@ +contract Test { + function f() public pure { + type(C).creationCode = new bytes(6); + type(C).runtimeCode = new bytes(6); + } +} +contract C {} +// ---- +// TypeError: (55-75): Expression has to be an lvalue. +// TypeError: (100-119): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/metaTypes/noArgForType.sol b/test/libsolidity/syntaxTests/metaTypes/noArgForType.sol new file mode 100644 index 00000000..542aaf53 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/noArgForType.sol @@ -0,0 +1,7 @@ +contract Test { + function creation() public pure returns (bytes memory) { + type(); + } +} +// ---- +// TypeError: (85-91): This function takes one argument, but 0 were provided. diff --git a/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol b/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol new file mode 100644 index 00000000..ec8d9784 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/runtimeCodeWarningAssembly.sol @@ -0,0 +1,17 @@ +contract Test { + function f() public pure returns (uint) { + return type(C).runtimeCode.length + + type(D).runtimeCode.length + + type(C).creationCode.length + + type(D).creationCode.length; + } +} +contract C { + constructor() public { assembly {} } +} +contract D is C { + constructor() public {} +} +// ---- +// Warning: (77-96): The constructor of the contract (or its base) uses inline assembly. Because of that, it might be that the deployed bytecode is different from type(...).runtimeCode. +// Warning: (118-137): The constructor of the contract (or its base) uses inline assembly. Because of that, it might be that the deployed bytecode is different from type(...).runtimeCode. diff --git a/test/libsolidity/syntaxTests/metaTypes/tooManyArgsForType.sol b/test/libsolidity/syntaxTests/metaTypes/tooManyArgsForType.sol new file mode 100644 index 00000000..61c2b779 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/tooManyArgsForType.sol @@ -0,0 +1,7 @@ +contract Test { + function creation() public pure returns (bytes memory) { + type(1, 2); + } +} +// ---- +// TypeError: (85-95): This function takes one argument, but 2 were provided. diff --git a/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierContractName.sol b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierContractName.sol new file mode 100644 index 00000000..144ca1c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierContractName.sol @@ -0,0 +1,3 @@ +contract type { } +// ---- +// ParserError: (9-13): Expected identifier but got 'type' diff --git a/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierFunction.sol b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierFunction.sol new file mode 100644 index 00000000..b7881f15 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierFunction.sol @@ -0,0 +1,6 @@ +contract Test { + function type() public pure { + } +} +// ---- +// ParserError: (29-33): Expected identifier but got 'type' diff --git a/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierParameter.sol b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierParameter.sol new file mode 100644 index 00000000..001ba840 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierParameter.sol @@ -0,0 +1,6 @@ +contract Test { + function f(uint type) public pure { + } +} +// ---- +// ParserError: (36-40): Expected ',' but got 'type' diff --git a/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierStateVariable.sol b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierStateVariable.sol new file mode 100644 index 00000000..fa827a33 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierStateVariable.sol @@ -0,0 +1,5 @@ +contract Test { + uint type; +} +// ---- +// ParserError: (25-29): Expected identifier but got 'type' diff --git a/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierVariable.sol b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierVariable.sol new file mode 100644 index 00000000..fa57698d --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/typeNotRegularIdentifierVariable.sol @@ -0,0 +1,7 @@ +contract Test { + function f() public pure { + uint type; + } +} +// ---- +// ParserError: (60-64): Expected ';' but got 'type' diff --git a/test/libsolidity/syntaxTests/metaTypes/typeOfContract.sol b/test/libsolidity/syntaxTests/metaTypes/typeOfContract.sol new file mode 100644 index 00000000..036c36e8 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/typeOfContract.sol @@ -0,0 +1,6 @@ +contract Test { + function f() public pure returns (bytes memory) { + type(Test); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/metaTypes/typeRecursive.sol b/test/libsolidity/syntaxTests/metaTypes/typeRecursive.sol new file mode 100644 index 00000000..0ce06786 --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/typeRecursive.sol @@ -0,0 +1,8 @@ +contract Test { + function f() public pure { + type(type(type(Test))); + } +} +// ---- +// TypeError: (65-75): Invalid type for argument in function call. Contract type required, but type(contract Test) provided. +// TypeError: (60-76): Invalid type for argument in function call. Contract type required, but tuple() provided. diff --git a/test/libsolidity/syntaxTests/metaTypes/unsupportedArgForType.sol b/test/libsolidity/syntaxTests/metaTypes/unsupportedArgForType.sol new file mode 100644 index 00000000..5c27d42f --- /dev/null +++ b/test/libsolidity/syntaxTests/metaTypes/unsupportedArgForType.sol @@ -0,0 +1,9 @@ +contract Test { + struct S { uint x; } + function f() public pure { + // Unsupported for now, but might be supported in the future + type(S); + } +} +// ---- +// TypeError: (154-155): Invalid type for argument in function call. Contract type required, but type(struct Test.S) provided. diff --git a/test/libsolidity/syntaxTests/types/encoding_fractional.sol b/test/libsolidity/syntaxTests/types/encoding_fractional.sol new file mode 100644 index 00000000..16c76d9a --- /dev/null +++ b/test/libsolidity/syntaxTests/types/encoding_fractional.sol @@ -0,0 +1,7 @@ +contract C { + function f1() public pure returns (bytes memory) { + return abi.encode(0.1, 1); + } +} +// ---- +// TypeError: (92-95): Fractional numbers cannot yet be encoded. diff --git a/test/libsolidity/syntaxTests/types/encoding_fractional_abiencoderv2.sol b/test/libsolidity/syntaxTests/types/encoding_fractional_abiencoderv2.sol new file mode 100644 index 00000000..80efa9c5 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/encoding_fractional_abiencoderv2.sol @@ -0,0 +1,9 @@ +pragma experimental ABIEncoderV2; +contract C { + function f1() public pure returns (bytes memory) { + return abi.encode(0.1, 1); + } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (126-129): Fractional numbers cannot yet be encoded. diff --git a/test/libsolidity/syntaxTests/types/encoding_packed_fractional.sol b/test/libsolidity/syntaxTests/types/encoding_packed_fractional.sol new file mode 100644 index 00000000..71080cb0 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/encoding_packed_fractional.sol @@ -0,0 +1,8 @@ +contract C { + function f1() public pure returns (bytes memory) { + return abi.encodePacked(0.1, 1); + } +} +// ---- +// TypeError: (98-101): Fractional numbers cannot yet be encoded. +// TypeError: (103-104): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. diff --git a/test/libsolidity/syntaxTests/types/encoding_packed_fractional_abiencoderv2.sol b/test/libsolidity/syntaxTests/types/encoding_packed_fractional_abiencoderv2.sol new file mode 100644 index 00000000..e82c3c9a --- /dev/null +++ b/test/libsolidity/syntaxTests/types/encoding_packed_fractional_abiencoderv2.sol @@ -0,0 +1,10 @@ +pragma experimental ABIEncoderV2; +contract C { + function f1() public pure returns (bytes memory) { + return abi.encodePacked(0.1, 1); + } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (132-135): Fractional numbers cannot yet be encoded. +// TypeError: (137-138): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 59cde4fe..306721a0 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -38,6 +38,7 @@ #include <libyul/optimiser/ExpressionSimplifier.h> #include <libyul/optimiser/UnusedPruner.h> #include <libyul/optimiser/ExpressionJoiner.h> +#include <libyul/optimiser/SSAReverser.h> #include <libyul/optimiser/SSATransform.h> #include <libyul/optimiser/RedundantAssignEliminator.h> #include <libyul/optimiser/StructuralSimplifier.h> @@ -223,6 +224,23 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); EquivalentFunctionCombiner::run(*m_ast); } + else if (m_optimizerStep == "ssaReverser") + { + disambiguate(); + SSAReverser::run(*m_ast); + } + else if (m_optimizerStep == "ssaAndBack") + { + disambiguate(); + // apply SSA + NameDispenser nameDispenser{*m_dialect, *m_ast}; + SSATransform::run(*m_ast, nameDispenser); + RedundantAssignEliminator::run(*m_dialect, *m_ast); + // reverse SSA + SSAReverser::run(*m_ast); + CommonSubexpressionEliminator{*m_dialect}(*m_ast); + UnusedPruner::runUntilStabilised(*m_dialect, *m_ast); + } else if (m_optimizerStep == "fullSuite") OptimiserSuite::run(*m_dialect, *m_ast, *m_analysisInfo); else diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi2.yul b/test/libyul/yulOptimizerTests/fullSuite/abi2.yul index 887399b6..41a52c67 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/abi2.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/abi2.yul @@ -1073,12 +1073,12 @@ // fullSuite // { // let _2 := mload(1) -// let _172 := mload(0) -// if slt(sub(_2, _172), 64) +// let _153 := mload(0) +// if slt(sub(_2, _153), 64) // { // revert(0, 0) // } -// sstore(0, and(calldataload(_172), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) +// sstore(0, and(calldataload(_153), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) // let x0, x1, x2, x3, x4 := abi_decode_tuple_t_addresst_uint256t_bytes_calldata_ptrt_enum$_Operation_$1949(mload(7), mload(8)) // sstore(x1, x0) // sstore(x3, x2) @@ -1093,40 +1093,40 @@ // value0_57 := and(calldataload(add(headStart_55, value4)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) // value1_58 := calldataload(add(headStart_55, 32)) // let offset_62 := calldataload(add(headStart_55, 64)) -// let _220 := 0xffffffffffffffff -// if gt(offset_62, _220) +// let _201 := 0xffffffffffffffff +// if gt(offset_62, _201) // { // revert(value4, value4) // } -// let _222 := add(headStart_55, offset_62) -// if iszero(slt(add(_222, 0x1f), dataEnd_56)) +// let _203 := add(headStart_55, offset_62) +// if iszero(slt(add(_203, 0x1f), dataEnd_56)) // { // revert(value4, value4) // } -// let abi_decode_length_15_116 := calldataload(_222) -// if gt(abi_decode_length_15_116, _220) +// let abi_decode_length_15_246 := calldataload(_203) +// if gt(abi_decode_length_15_246, _201) // { // revert(value4, value4) // } -// if gt(add(add(_222, abi_decode_length_15_116), 32), dataEnd_56) +// if gt(add(add(_203, abi_decode_length_15_246), 32), dataEnd_56) // { // revert(value4, value4) // } -// value2_59 := add(_222, 32) -// value3 := abi_decode_length_15_116 -// let _225 := calldataload(add(headStart_55, 96)) -// if iszero(lt(_225, 3)) +// value2_59 := add(_203, 32) +// value3 := abi_decode_length_15_246 +// let _206 := calldataload(add(headStart_55, 96)) +// if iszero(lt(_206, 3)) // { // revert(value4, value4) // } -// value4 := _225 +// value4 := _206 // } // function abi_encode_tuple_t_bytes32_t_address_t_uint256_t_bytes32_t_enum$_Operation_$1949_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint256__to_t_bytes32_t_address_t_uint256_t_bytes32_t_uint8_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint256_(headStart_252, value10_253, value9_254, value8_255, value7_256, value6_257, value5_258, value4_259, value3_260, value2_261, value1_262, value0_263) -> tail_264 // { // tail_264 := add(headStart_252, 352) // mstore(headStart_252, value0_263) -// let _439 := 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -// mstore(add(headStart_252, 32), and(value1_262, _439)) +// let _413 := 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +// mstore(add(headStart_252, 32), and(value1_262, _413)) // mstore(add(headStart_252, 64), value2_261) // mstore(add(headStart_252, 96), value3_260) // if iszero(lt(value4_259, 3)) @@ -1137,8 +1137,8 @@ // mstore(add(headStart_252, 160), value5_258) // mstore(add(headStart_252, 192), value6_257) // mstore(add(headStart_252, 224), value7_256) -// mstore(add(headStart_252, 256), and(value8_255, _439)) -// mstore(add(headStart_252, 288), and(value9_254, _439)) +// mstore(add(headStart_252, 256), and(value8_255, _413)) +// mstore(add(headStart_252, 288), and(value9_254, _413)) // mstore(add(headStart_252, 320), value10_253) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul index a8cac6c6..d38025ae 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul @@ -460,12 +460,12 @@ // { // let _1 := 0x20 // let _2 := 0 -// let _268 := mload(_2) +// let _218 := mload(_2) // let abi_encode_pos := _1 -// let abi_encode_length_68 := mload(_268) +// let abi_encode_length_68 := mload(_218) // mstore(_1, abi_encode_length_68) // abi_encode_pos := 64 -// let abi_encode_srcPtr := add(_268, _1) +// let abi_encode_srcPtr := add(_218, _1) // let abi_encode_i_69 := _2 // for { // } @@ -474,66 +474,64 @@ // abi_encode_i_69 := add(abi_encode_i_69, 1) // } // { -// let _668 := mload(abi_encode_srcPtr) -// let abi_encode_pos_71_760 := abi_encode_pos -// let abi_encode_srcPtr_73_762 := _668 -// let abi_encode_i_74_763 := _2 +// let _580 := mload(abi_encode_srcPtr) +// let abi_encode_pos_71_672 := abi_encode_pos +// let abi_encode_srcPtr_73_674 := _580 +// let abi_encode_i_74_675 := _2 // for { // } -// lt(abi_encode_i_74_763, 0x3) +// lt(abi_encode_i_74_675, 0x3) // { -// abi_encode_i_74_763 := add(abi_encode_i_74_763, 1) +// abi_encode_i_74_675 := add(abi_encode_i_74_675, 1) // } // { -// mstore(abi_encode_pos_71_760, and(mload(abi_encode_srcPtr_73_762), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) -// abi_encode_srcPtr_73_762 := add(abi_encode_srcPtr_73_762, _1) -// abi_encode_pos_71_760 := add(abi_encode_pos_71_760, _1) +// mstore(abi_encode_pos_71_672, and(mload(abi_encode_srcPtr_73_674), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) +// abi_encode_srcPtr_73_674 := add(abi_encode_srcPtr_73_674, _1) +// abi_encode_pos_71_672 := add(abi_encode_pos_71_672, _1) // } // abi_encode_srcPtr := add(abi_encode_srcPtr, _1) // abi_encode_pos := add(abi_encode_pos, 0x60) // } -// let _270 := mload(64) -// let _271 := mload(_1) -// if slt(sub(_270, _271), 128) +// let _220 := mload(64) +// let _221 := mload(_1) +// if slt(sub(_220, _221), 128) // { // revert(_2, _2) // } -// let abi_decode_offset_64 := calldataload(add(_271, 64)) +// let abi_decode_offset_64 := calldataload(add(_221, 64)) // let abi_decode__74 := 0xffffffffffffffff // if gt(abi_decode_offset_64, abi_decode__74) // { // revert(_2, _2) // } -// let abi_decode_value2_367 := abi_decode_t_array$_t_uint256_$dyn_memory_ptr(add(_271, abi_decode_offset_64), _270) -// let abi_decode_offset_65 := calldataload(add(_271, 96)) +// let abi_decode_value2_317 := abi_decode_t_array$_t_uint256_$dyn_memory_ptr(add(_221, abi_decode_offset_64), _220) +// let abi_decode_offset_65 := calldataload(add(_221, 96)) // if gt(abi_decode_offset_65, abi_decode__74) // { // revert(_2, _2) // } -// let abi_decode_value3_368 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(_271, abi_decode_offset_65), _270) -// sstore(calldataload(_271), calldataload(add(_271, _1))) -// sstore(abi_decode_value2_367, abi_decode_value3_368) +// let abi_decode_value3_318 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(_221, abi_decode_offset_65), _220) +// sstore(calldataload(_221), calldataload(add(_221, _1))) +// sstore(abi_decode_value2_317, abi_decode_value3_318) // sstore(_2, abi_encode_pos) // function abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(offset_3, end_4) -> array_5 // { // if iszero(slt(add(offset_3, 0x1f), end_4)) // { -// revert(0, 0) +// revert(array_5, array_5) // } // let length_6 := calldataload(offset_3) -// let array_5_115 := allocateMemory(array_allocation_size_t_array$_t_address_$dyn_memory(length_6)) -// array_5 := array_5_115 -// let dst_7 := array_5_115 -// mstore(array_5_115, length_6) +// array_5 := allocateMemory(array_allocation_size_t_array$_t_address_$dyn_memory(length_6)) +// let dst_7 := array_5 +// mstore(array_5, length_6) // let _16 := 0x20 -// dst_7 := add(array_5_115, _16) +// dst_7 := add(array_5, _16) // let src_8 := add(offset_3, _16) // if gt(add(add(offset_3, mul(length_6, 0x40)), _16), end_4) // { // revert(0, 0) // } -// let i_9_346 := 0 -// let i_9 := i_9_346 +// let i_9 := 0 // for { // } // lt(i_9, length_6) @@ -543,17 +541,17 @@ // { // if iszero(slt(add(src_8, 0x1f), end_4)) // { -// revert(i_9_346, i_9_346) +// revert(0, 0) // } -// let abi_decode_array_13_124 := allocateMemory(array_allocation_size_t_array$_t_uint256_$2_memory(0x2)) -// let abi_decode_dst_15 := abi_decode_array_13_124 +// let abi_decode_dst_15 := allocateMemory(array_allocation_size_t_array$_t_uint256_$2_memory(0x2)) +// let abi_decode_dst_15_1155 := abi_decode_dst_15 // let abi_decode_src_16 := src_8 -// let abi_decode__289 := add(src_8, 0x40) -// if gt(abi_decode__289, end_4) +// let abi_decode__239 := add(src_8, 0x40) +// if gt(abi_decode__239, end_4) // { -// revert(i_9_346, i_9_346) +// revert(0, 0) // } -// let abi_decode_i_17 := i_9_346 +// let abi_decode_i_17 := 0 // for { // } // lt(abi_decode_i_17, 0x2) @@ -565,24 +563,23 @@ // abi_decode_dst_15 := add(abi_decode_dst_15, _16) // abi_decode_src_16 := add(abi_decode_src_16, _16) // } -// mstore(dst_7, abi_decode_array_13_124) +// mstore(dst_7, abi_decode_dst_15_1155) // dst_7 := add(dst_7, _16) -// src_8 := abi_decode__289 +// src_8 := abi_decode__239 // } // } // function abi_decode_t_array$_t_uint256_$dyn_memory_ptr(offset_27, end_28) -> array_29 // { // if iszero(slt(add(offset_27, 0x1f), end_28)) // { -// revert(0, 0) +// revert(array_29, array_29) // } // let length_30 := calldataload(offset_27) -// let array_29_131 := allocateMemory(array_allocation_size_t_array$_t_address_$dyn_memory(length_30)) -// array_29 := array_29_131 -// let dst_31 := array_29_131 -// mstore(array_29_131, length_30) +// array_29 := allocateMemory(array_allocation_size_t_array$_t_address_$dyn_memory(length_30)) +// let dst_31 := array_29 +// mstore(array_29, length_30) // let _52 := 0x20 -// dst_31 := add(array_29_131, _52) +// dst_31 := add(array_29, _52) // let src_32 := add(offset_27, _52) // if gt(add(add(offset_27, mul(length_30, _52)), _52), end_28) // { @@ -603,10 +600,9 @@ // } // function allocateMemory(size) -> memPtr // { -// let memPtr_157 := mload(64) -// memPtr := memPtr_157 -// let newFreePtr := add(memPtr_157, size) -// if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr_157)) +// memPtr := mload(64) +// let newFreePtr := add(memPtr, size) +// if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) // { // revert(0, 0) // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul index fc09b5d9..868c6b01 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul @@ -245,17 +245,16 @@ // mstore(0x00, 404) // revert(0x00, 0x20) // } -// let validateJo_kn_287 := calldataload(add(calldatasize(), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40)) -// let validateJo_kn := validateJo_kn_287 +// let validateJo_kn := calldataload(add(calldatasize(), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40)) // let validateJo__24 := 0x2a0 // mstore(validateJo__24, caller()) -// mstore(0x2c0, validateJo_kn_287) +// mstore(0x2c0, validateJo_kn) // mstore(0x2e0, validateJo_m) -// validateJo_kn := mulmod(sub(validateJo_gen_order, validateJo_kn_287), validateJo_challenge, validateJo_gen_order) +// validateJo_kn := mulmod(sub(validateJo_gen_order, validateJo_kn), validateJo_challenge, validateJo_gen_order) // hashCommitments(validateJo_notes, validateJo_n) // let validateJo_b := add(0x300, mul(validateJo_n, validateJo__6)) -// let validateJo_i_290 := 0 -// let validateJo_i := validateJo_i_290 +// let validateJo_i := 0 +// let validateJo_i_1306 := validateJo_i // for { // } // lt(validateJo_i, validateJo_n) @@ -264,11 +263,10 @@ // } // { // let validateJo__34 := 0x20 -// let validateJo__373 := add(validateJo__10, mul(validateJo_i, 0xc0)) -// let validateJo_noteIndex := add(validateJo__373, 0x24) -// let validateJo_k := validateJo_i_290 -// let validateJo_a_292 := calldataload(add(validateJo__373, 0x44)) -// let validateJo_a := validateJo_a_292 +// let validateJo__351 := add(validateJo__10, mul(validateJo_i, 0xc0)) +// let validateJo_noteIndex := add(validateJo__351, 0x24) +// let validateJo_k := validateJo_i_1306 +// let validateJo_a := calldataload(add(validateJo__351, 0x44)) // let validateJo_c := validateJo_challenge // let validateJo__39 := add(validateJo_i, 0x01) // switch eq(validateJo__39, validateJo_n) @@ -282,36 +280,34 @@ // case 0 { // validateJo_k := calldataload(validateJo_noteIndex) // } -// validateCommitment(validateJo_noteIndex, validateJo_k, validateJo_a_292) +// validateCommitment(validateJo_noteIndex, validateJo_k, validateJo_a) // switch gt(validateJo__39, validateJo_m) // case 1 { // validateJo_kn := addmod(validateJo_kn, sub(validateJo_gen_order, validateJo_k), validateJo_gen_order) -// let validateJo_x := mod(mload(validateJo_i_290), validateJo_gen_order) +// let validateJo_x := mod(mload(validateJo_i_1306), validateJo_gen_order) // validateJo_k := mulmod(validateJo_k, validateJo_x, validateJo_gen_order) -// validateJo_a := mulmod(validateJo_a_292, validateJo_x, validateJo_gen_order) +// validateJo_a := mulmod(validateJo_a, validateJo_x, validateJo_gen_order) // validateJo_c := mulmod(validateJo_challenge, validateJo_x, validateJo_gen_order) -// mstore(validateJo_i_290, keccak256(validateJo_i_290, validateJo__34)) +// mstore(validateJo_i_1306, keccak256(validateJo_i_1306, validateJo__34)) // } // case 0 { // validateJo_kn := addmod(validateJo_kn, validateJo_k, validateJo_gen_order) // } // let validateJo__52 := 0x40 -// calldatacopy(0xe0, add(validateJo__373, 164), validateJo__52) -// calldatacopy(validateJo__34, add(validateJo__373, 100), validateJo__52) +// calldatacopy(0xe0, add(validateJo__351, 164), validateJo__52) +// calldatacopy(validateJo__34, add(validateJo__351, 100), validateJo__52) // let validateJo__61 := 0x120 // mstore(validateJo__61, sub(validateJo_gen_order, validateJo_c)) // let validateJo__62 := 0x60 // mstore(validateJo__62, validateJo_k) // mstore(0xc0, validateJo_a) // let validateJo__65 := 0x1a0 -// let validateJo_result_302 := call(gas(), 7, validateJo_i_290, 0xe0, validateJo__62, validateJo__65, validateJo__52) -// let validateJo_result := validateJo_result_302 -// let validateJo_result_303 := and(validateJo_result_302, call(gas(), 7, validateJo_i_290, validateJo__34, validateJo__62, validateJo__61, validateJo__52)) +// let validateJo_result := call(gas(), 7, validateJo_i_1306, 0xe0, validateJo__62, validateJo__65, validateJo__52) +// let validateJo_result_303 := and(validateJo_result, call(gas(), 7, validateJo_i_1306, validateJo__34, validateJo__62, validateJo__61, validateJo__52)) // let validateJo__80 := 0x160 -// let validateJo_result_304 := and(validateJo_result_303, call(gas(), 7, validateJo_i_290, validateJo__6, validateJo__62, validateJo__80, validateJo__52)) -// let validateJo_result_305 := and(validateJo_result_304, call(gas(), 6, validateJo_i_290, validateJo__61, validateJo__6, validateJo__80, validateJo__52)) -// let validateJo_result_306 := and(validateJo_result_305, call(gas(), 6, validateJo_i_290, validateJo__80, validateJo__6, validateJo_b, validateJo__52)) -// validateJo_result := validateJo_result_306 +// let validateJo_result_304 := and(validateJo_result_303, call(gas(), 7, validateJo_i_1306, validateJo__6, validateJo__62, validateJo__80, validateJo__52)) +// let validateJo_result_305 := and(validateJo_result_304, call(gas(), 6, validateJo_i_1306, validateJo__61, validateJo__6, validateJo__80, validateJo__52)) +// validateJo_result := and(validateJo_result_305, call(gas(), 6, validateJo_i_1306, validateJo__80, validateJo__6, validateJo_b, validateJo__52)) // if eq(validateJo_i, validateJo_m) // { // mstore(0x260, mload(validateJo__34)) @@ -323,14 +319,14 @@ // { // mstore(validateJo__62, validateJo_c) // let validateJo__120 := 0x220 -// let validateJo_result_307 := and(validateJo_result_306, call(gas(), 7, validateJo_i_290, validateJo__34, validateJo__62, validateJo__120, validateJo__52)) -// let validateJo_result_308 := and(validateJo_result_307, call(gas(), 6, validateJo_i_290, validateJo__120, validateJo__6, 0x260, validateJo__52)) -// validateJo_result := and(validateJo_result_308, call(gas(), 6, validateJo_i_290, validateJo__65, validateJo__6, 0x1e0, validateJo__52)) +// let validateJo_result_307 := and(validateJo_result, call(gas(), 7, validateJo_i_1306, validateJo__34, validateJo__62, validateJo__120, validateJo__52)) +// let validateJo_result_308 := and(validateJo_result_307, call(gas(), 6, validateJo_i_1306, validateJo__120, validateJo__6, 0x260, validateJo__52)) +// validateJo_result := and(validateJo_result_308, call(gas(), 6, validateJo_i_1306, validateJo__65, validateJo__6, 0x1e0, validateJo__52)) // } // if iszero(validateJo_result) // { -// mstore(validateJo_i_290, 400) -// revert(validateJo_i_290, validateJo__34) +// mstore(validateJo_i_1306, 400) +// revert(validateJo_i_1306, validateJo__34) // } // validateJo_b := add(validateJo_b, validateJo__52) // } @@ -340,13 +336,13 @@ // } // if iszero(eq(mod(keccak256(validateJo__24, add(validateJo_b, 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd60)), validateJo_gen_order), validateJo_challenge)) // { -// mstore(validateJo_i_290, 404) -// revert(validateJo_i_290, 0x20) +// mstore(validateJo_i_1306, 404) +// revert(validateJo_i_1306, 0x20) // } -// mstore(validateJo_i_290, 0x01) -// return(validateJo_i_290, 0x20) -// mstore(validateJo_i_290, 404) -// revert(validateJo_i_290, 0x20) +// mstore(validateJo_i_1306, 0x01) +// return(validateJo_i_1306, 0x20) +// mstore(validateJo_i_1306, 404) +// revert(validateJo_i_1306, 0x20) // function validatePairing(t2) // { // let t2_x_1 := calldataload(t2) diff --git a/test/libyul/yulOptimizerTests/fullSuite/medium.yul b/test/libyul/yulOptimizerTests/fullSuite/medium.yul index b10c6c69..1d07cd03 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/medium.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/medium.yul @@ -21,8 +21,8 @@ // { // let allocate__19 := 0x40 // mstore(allocate__19, add(mload(allocate__19), 0x20)) -// let allocate_p_24_41 := mload(allocate__19) -// mstore(allocate__19, add(allocate_p_24_41, allocate__19)) -// mstore(add(allocate_p_24_41, 96), 2) +// let allocate_p_35_39 := mload(allocate__19) +// mstore(allocate__19, add(allocate_p_35_39, allocate__19)) +// mstore(add(allocate_p_35_39, 96), 2) // mstore(allocate__19, 0x20) // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul b/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul new file mode 100644 index 00000000..204b444e --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul @@ -0,0 +1,62 @@ +{ + // This is an abi decode function with the SSA transform applied once. + // This test is supposed to verify that the SSA transform is correctly reversed by the full suite. + function abi_decode_t_bytes_calldata_ptr(offset_12, end_13) -> arrayPos_14, length_15 + { + if iszero(slt(add(offset_12, 0x1f), end_13)) + { + revert(0, 0) + } + let length_15_1 := calldataload(offset_12) + length_15 := length_15_1 + if gt(length_15_1, 0xffffffffffffffff) + { + revert(0, 0) + } + let arrayPos_14_2 := add(offset_12, 0x20) + arrayPos_14 := arrayPos_14_2 + if gt(add(arrayPos_14_2, mul(length_15_1, 0x1)), end_13) + { + revert(0, 0) + } + } + + // prevent inlining + let a,b := abi_decode_t_bytes_calldata_ptr(mload(0),mload(1)) + a,b := abi_decode_t_bytes_calldata_ptr(a,b) + a,b := abi_decode_t_bytes_calldata_ptr(a,b) + a,b := abi_decode_t_bytes_calldata_ptr(a,b) + a,b := abi_decode_t_bytes_calldata_ptr(a,b) + a,b := abi_decode_t_bytes_calldata_ptr(a,b) + a,b := abi_decode_t_bytes_calldata_ptr(a,b) + mstore(a,b) +} +// ---- +// fullSuite +// { +// let a, b := abi_decode_t_bytes_calldata_ptr(mload(0), mload(1)) +// a, b := abi_decode_t_bytes_calldata_ptr(a, b) +// a, b := abi_decode_t_bytes_calldata_ptr(a, b) +// a, b := abi_decode_t_bytes_calldata_ptr(a, b) +// a, b := abi_decode_t_bytes_calldata_ptr(a, b) +// a, b := abi_decode_t_bytes_calldata_ptr(a, b) +// a, b := abi_decode_t_bytes_calldata_ptr(a, b) +// mstore(a, b) +// function abi_decode_t_bytes_calldata_ptr(offset_12, end_13) -> arrayPos_14, length_15 +// { +// if iszero(slt(add(offset_12, 0x1f), end_13)) +// { +// revert(0, 0) +// } +// length_15 := calldataload(offset_12) +// if gt(length_15, 0xffffffffffffffff) +// { +// revert(0, 0) +// } +// arrayPos_14 := add(offset_12, 0x20) +// if gt(add(add(offset_12, length_15), 0x20), end_13) +// { +// revert(0, 0) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul b/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul new file mode 100644 index 00000000..2e178f31 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul @@ -0,0 +1,23 @@ +{ + let a := mload(0) + let b := mload(1) + if mload(2) { + a := mload(b) + b := mload(a) + a := mload(b) + b := mload(a) + } + mstore(a, b) +} +// ---- +// fullSuite +// { +// let a := mload(0) +// let b := mload(1) +// if mload(2) +// { +// a := mload(mload(mload(b))) +// b := mload(a) +// } +// mstore(a, b) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul new file mode 100644 index 00000000..18498e61 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul @@ -0,0 +1,36 @@ +{ + for { + let a := mload(0) + let b := mload(1) + } + lt(mload(a),mload(b)) + { + a := mload(b) + } + { + b := mload(a) + a := mload(b) + a := mload(b) + a := mload(b) + b := mload(a) + } +} +// ---- +// ssaAndBack +// { +// for { +// let a := mload(0) +// let b := mload(1) +// } +// lt(mload(a), mload(b)) +// { +// a := mload(b) +// } +// { +// let b_3 := mload(a) +// pop(mload(b_3)) +// pop(mload(b_3)) +// let a_6 := mload(b_3) +// b := mload(a_6) +// } +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul new file mode 100644 index 00000000..23c433d1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul @@ -0,0 +1,18 @@ +{ + let a := mload(0) + a := mload(1) + a := mload(2) + a := mload(3) + a := mload(4) + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// pop(mload(0)) +// pop(mload(1)) +// pop(mload(2)) +// pop(mload(3)) +// let a_5 := mload(4) +// mstore(a_5, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul new file mode 100644 index 00000000..fd5981ef --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul @@ -0,0 +1,22 @@ +{ + let a := mload(0) + if mload(1) + { + a := mload(1) + a := mload(2) + a := mload(3) + } + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// if mload(1) +// { +// pop(mload(1)) +// pop(mload(2)) +// a := mload(3) +// } +// mstore(a, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul new file mode 100644 index 00000000..b0b3efb5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul @@ -0,0 +1,25 @@ +{ + let a := mload(0) + let b := mload(1) + if mload(2) { + a := mload(b) + b := mload(a) + a := mload(b) + b := mload(a) + } + mstore(a, b) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// let b := mload(1) +// if mload(2) +// { +// let a_3 := mload(b) +// let b_4 := mload(a_3) +// a := mload(b_4) +// b := mload(a) +// } +// mstore(a, b) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul new file mode 100644 index 00000000..50f56b87 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul @@ -0,0 +1,38 @@ +{ + let a := mload(0) + let b := mload(1) + switch mload(2) + case 0 { + a := mload(b) + b := mload(a) + a := mload(b) + b := mload(a) + } + default { + b := mload(a) + a := mload(b) + b := mload(a) + a := mload(b) + } + mstore(a, b) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// let b := mload(1) +// switch mload(2) +// case 0 { +// let a_3 := mload(b) +// let b_4 := mload(a_3) +// a := mload(b_4) +// b := mload(a) +// } +// default { +// let b_7 := mload(a) +// let a_8 := mload(b_7) +// b := mload(a_8) +// a := mload(b) +// } +// mstore(a, b) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul new file mode 100644 index 00000000..1efbbde7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul @@ -0,0 +1,32 @@ +{ + let a := mload(0) + switch mload(1) + case 0 { + a := mload(1) + a := mload(2) + a := mload(3) + } + default { + a := mload(4) + a := mload(5) + a := mload(6) + } + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// switch mload(1) +// case 0 { +// pop(mload(1)) +// pop(mload(2)) +// a := mload(3) +// } +// default { +// pop(mload(4)) +// pop(mload(5)) +// a := mload(6) +// } +// mstore(a, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul b/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul new file mode 100644 index 00000000..912940c5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul @@ -0,0 +1,12 @@ +{ + let a := mload(0) + a := mload(1) + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// pop(mload(0)) +// let a_2 := mload(1) +// mstore(a_2, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul new file mode 100644 index 00000000..5185245c --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul @@ -0,0 +1,18 @@ +{ + let a := mload(0) + if mload(1) + { + a := mload(1) + } + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// if mload(1) +// { +// a := mload(1) +// } +// mstore(a, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul new file mode 100644 index 00000000..e0e53b3f --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul @@ -0,0 +1,24 @@ +{ + let a := mload(0) + switch mload(1) + case 0 { + a := mload(1) + } + default { + a := mload(2) + } + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// switch mload(1) +// case 0 { +// a := mload(1) +// } +// default { +// a := mload(2) +// } +// mstore(a, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul b/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul new file mode 100644 index 00000000..d2ba6471 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul @@ -0,0 +1,45 @@ +{ + function abi_decode_t_bytes_calldata_ptr(offset_12, end_13) -> arrayPos_14, length_15 + { + if iszero(slt(add(offset_12, 0x1f), end_13)) + { + revert(0, 0) + } + length_15 := calldataload(offset_12) + if gt(length_15, 0xffffffffffffffff) + { + revert(0, 0) + } + arrayPos_14 := add(offset_12, 0x20) + if gt(add(add(offset_12, length_15), 0x20), end_13) + { + revert(0, 0) + } + } + // prevent removal of the function + let a,b := abi_decode_t_bytes_calldata_ptr(mload(0),mload(1)) + mstore(a,b) +} +// ---- +// ssaAndBack +// { +// function abi_decode_t_bytes_calldata_ptr(offset_12, end_13) -> arrayPos_14, length_15 +// { +// if iszero(slt(add(offset_12, 0x1f), end_13)) +// { +// revert(arrayPos_14, arrayPos_14) +// } +// length_15 := calldataload(offset_12) +// if gt(length_15, 0xffffffffffffffff) +// { +// revert(arrayPos_14, arrayPos_14) +// } +// arrayPos_14 := add(offset_12, 0x20) +// if gt(add(add(offset_12, length_15), 0x20), end_13) +// { +// revert(0, 0) +// } +// } +// let a, b := abi_decode_t_bytes_calldata_ptr(mload(0), mload(1)) +// mstore(a, b) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul b/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul new file mode 100644 index 00000000..9f2a046e --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul @@ -0,0 +1,20 @@ +{ + let a := mload(0) + let b := mload(a) + a := mload(b) + b := mload(a) + a := mload(b) + b := mload(a) + mstore(a, b) +} +// ---- +// ssaAndBack +// { +// let a_1 := mload(0) +// let b_2 := mload(a_1) +// let a_3 := mload(b_2) +// let b_4 := mload(a_3) +// let a_5 := mload(b_4) +// let b_6 := mload(a_5) +// mstore(a_5, b_6) +// } diff --git a/test/libyul/yulOptimizerTests/ssaReverser/abi_example.yul b/test/libyul/yulOptimizerTests/ssaReverser/abi_example.yul new file mode 100644 index 00000000..923a42ba --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaReverser/abi_example.yul @@ -0,0 +1,44 @@ +{ + function abi_decode_t_bytes_calldata_ptr(offset_12, end_13) -> arrayPos_14, length_15 + { + if iszero(slt(add(offset_12, 0x1f), end_13)) + { + revert(0, 0) + } + let length_15_1 := calldataload(offset_12) + length_15 := length_15_1 + if gt(length_15_1, 0xffffffffffffffff) + { + revert(0, 0) + } + let arrayPos_14_2 := add(offset_12, 0x20) + arrayPos_14 := arrayPos_14_2 + if gt(add(arrayPos_14_2, mul(length_15_1, 0x1)), end_13) + { + revert(0, 0) + } + } +} +// ---- +// ssaReverser +// { +// function abi_decode_t_bytes_calldata_ptr(offset_12, end_13) -> arrayPos_14, length_15 +// { +// if iszero(slt(add(offset_12, 0x1f), end_13)) +// { +// revert(0, 0) +// } +// length_15 := calldataload(offset_12) +// let length_15_1 := length_15 +// if gt(length_15_1, 0xffffffffffffffff) +// { +// revert(0, 0) +// } +// arrayPos_14 := add(offset_12, 0x20) +// let arrayPos_14_2 := arrayPos_14 +// if gt(add(arrayPos_14_2, mul(length_15_1, 0x1)), end_13) +// { +// revert(0, 0) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/ssaReverser/simple.yul b/test/libyul/yulOptimizerTests/ssaReverser/simple.yul new file mode 100644 index 00000000..eba1f5f1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaReverser/simple.yul @@ -0,0 +1,14 @@ +{ + let a := mload(1) + let a_1 := mload(0) + a := a_1 + mstore(a_1, 0) +} +// ---- +// ssaReverser +// { +// let a := mload(1) +// a := mload(0) +// let a_1 := a +// mstore(a_1, 0) +// } diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index efd1ba05..7203ef54 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -46,6 +46,7 @@ #include <libyul/optimiser/UnusedPruner.h> #include <libyul/optimiser/ExpressionJoiner.h> #include <libyul/optimiser/RedundantAssignEliminator.h> +#include <libyul/optimiser/SSAReverser.h> #include <libyul/optimiser/SSATransform.h> #include <libyul/optimiser/StructuralSimplifier.h> #include <libyul/optimiser/VarDeclInitializer.h> @@ -129,7 +130,7 @@ public: cout << "(q)quit/(f)flatten/(c)se/initialize var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl; cout << " (e)xpr inline/(i)nline/(s)implify/(u)nusedprune/ss(a) transform/" << endl; cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-pre-rewriter/" << endl; - cout << " s(t)ructural simplifier/equi(v)alent function combiner? " << endl; + cout << " s(t)ructural simplifier/equi(v)alent function combiner/ssa re(V)erser? " << endl; cout.flush(); int option = readStandardInputChar(); cout << ' ' << char(option) << endl; @@ -188,6 +189,9 @@ public: case 'v': EquivalentFunctionCombiner::run(*m_ast); break; + case 'V': + SSAReverser::run(*m_ast); + break; default: cout << "Unknown option." << endl; } |
