From 4368da0201221b418a631fa3049f51722f4d1817 Mon Sep 17 00:00:00 2001 From: Marenz Date: Wed, 6 Oct 2021 14:12:06 +0200 Subject: [PATCH 01/62] Fix ICE when printing an error message related to mappings --- Changelog.md | 1 + libsolidity/ast/Types.cpp | 5 ++++ libsolidity/ast/Types.h | 2 +- .../user_defined_types_mapping_storage.sol | 28 +++++++++++++++++++ .../syntaxTests/types/mapping/int_mapping.sol | 5 ++++ .../user_defined_types_mapping_memory.sol | 6 ++++ 6 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/semanticTests/types/mapping/user_defined_types_mapping_storage.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/int_mapping.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/user_defined_types_mapping_memory.sol diff --git a/Changelog.md b/Changelog.md index 32a5dbe5c..74e20d4b8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Compiler Features: Bugfixes: * Commandline Interface: Fix extra newline character being appended to sources passed through standard input, affecting their hashes. * SMTChecker: Fix internal error in magic type access (``block``, ``msg``, ``tx``). + * TypeChecker: Fix internal error when using user defined value types in public library functions. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index b1a77cf89..70e3ec298 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2559,6 +2559,11 @@ string UserDefinedValueType::toString(bool /* _short */) const return *definition().annotation().canonicalName; } +string UserDefinedValueType::canonicalName() const +{ + return *definition().annotation().canonicalName; +} + vector> UserDefinedValueType::makeStackItems() const { return underlyingType().stackItems(); diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 2220875b1..334e69ba1 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1141,7 +1141,7 @@ public: } std::string toString(bool _short) const override; - std::string canonicalName() const override { solAssert(false, ""); } + std::string canonicalName() const override; std::string signatureInExternalFunction(bool) const override { solAssert(false, ""); } protected: diff --git a/test/libsolidity/semanticTests/types/mapping/user_defined_types_mapping_storage.sol b/test/libsolidity/semanticTests/types/mapping/user_defined_types_mapping_storage.sol new file mode 100644 index 000000000..ae6756822 --- /dev/null +++ b/test/libsolidity/semanticTests/types/mapping/user_defined_types_mapping_storage.sol @@ -0,0 +1,28 @@ +type A is uint; +type B is uint; + +library L { + function f(mapping(A=>B) storage _m, B _v) public { _m[A.wrap(uint(2))] = _v; } + function f(mapping(uint=>uint) storage _m, uint _v) public { _m[uint(3)] = _v; } +} + +contract C { + mapping(uint=>uint) uintMap; + mapping(A=>B) abMap; + + function testAB() public returns (bool) { + L.f(abMap, B.wrap(3)); + return B.unwrap(abMap[A.wrap(uint(2))]) == 3; + } + function testUint() public returns (bool) { + L.f(uintMap, 4); + return uintMap[3] == 4; + } +} + +// ==== +// compileViaYul: also +// ---- +// library: L +// testAB() -> true +// testUint() -> true diff --git a/test/libsolidity/syntaxTests/types/mapping/int_mapping.sol b/test/libsolidity/syntaxTests/types/mapping/int_mapping.sol new file mode 100644 index 000000000..c041271e1 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/int_mapping.sol @@ -0,0 +1,5 @@ +library L { + function f(mapping(uint=>uint) memory) public {} +} +// ---- +// TypeError 4061: (25-51): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping. diff --git a/test/libsolidity/syntaxTests/types/mapping/user_defined_types_mapping_memory.sol b/test/libsolidity/syntaxTests/types/mapping/user_defined_types_mapping_memory.sol new file mode 100644 index 000000000..51b3c0388 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/user_defined_types_mapping_memory.sol @@ -0,0 +1,6 @@ +type T is uint; +library L { + function f(mapping(T=>T) memory) public {} +} +// ---- +// TypeError 4061: (41-61): Type mapping(T => T) is only valid in storage because it contains a (nested) mapping. From 4054e2a28fc4b3f211d3868ad5e8d485745b6a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 6 Oct 2021 18:24:10 +0200 Subject: [PATCH 02/62] compileFull(): Print only file names, not their content in case of failure --- scripts/common_cmdline.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/common_cmdline.sh b/scripts/common_cmdline.sh index 6718ca5b5..0854b5f04 100644 --- a/scripts/common_cmdline.sh +++ b/scripts/common_cmdline.sh @@ -99,7 +99,7 @@ function compileFull() printError "Inside directory:" echo " $(pwd)" printError "Input was:" - cat -- "${files[@]}" + echo "${files[@]}" false fi } From 476c76b54eeb80bae0f425a562ab5fdc84534221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 6 Oct 2021 18:32:06 +0200 Subject: [PATCH 03/62] compileFull(): Use find instead of /*/*, which requires ignoring missing files --- scripts/common_cmdline.sh | 2 +- test/cmdlineTests.sh | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/common_cmdline.sh b/scripts/common_cmdline.sh index 0854b5f04..15d93f562 100644 --- a/scripts/common_cmdline.sh +++ b/scripts/common_cmdline.sh @@ -20,7 +20,7 @@ # ------------------------------------------------------------------------------ YULARGS=(--strict-assembly) -FULLARGS=(--optimize --ignore-missing --combined-json "abi,asm,ast,bin,bin-runtime,devdoc,hashes,metadata,opcodes,srcmap,srcmap-runtime,userdoc") +FULLARGS=(--optimize --combined-json "abi,asm,ast,bin,bin-runtime,devdoc,hashes,metadata,opcodes,srcmap,srcmap-runtime,userdoc") OLDARGS=(--optimize --combined-json "abi,asm,ast,bin,bin-runtime,devdoc,interface,metadata,opcodes,srcmap,srcmap-runtime,userdoc") function compileFull() { diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index c413eef0f..1304da8af 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -424,7 +424,8 @@ printTask "Compiling various other contracts and libraries..." do echo " - $dir" cd "$dir" - compileFull --expect-warnings ./*.sol ./*/*.sol + # shellcheck disable=SC2046 # These file names are not supposed to contain spaces. + compileFull --expect-warnings $(find . -name '*.sol') cd .. done ) From 79d9d5bf0d48a608ba7a2b3baddcfcb5367347fb Mon Sep 17 00:00:00 2001 From: Sreekesh V <61742339+v-sreekesh@users.noreply.github.com> Date: Sat, 21 Aug 2021 21:33:35 +0530 Subject: [PATCH 04/62] Change optimizer sequence validations to allow nested brackets --- libyul/optimiser/Suite.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 480a542a3..80b73f1cb 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -78,6 +78,8 @@ #include #include +#include + using namespace std; using namespace solidity; using namespace solidity::yul; @@ -269,7 +271,7 @@ map const& OptimiserSuite::stepAbbreviationToNameMap() void OptimiserSuite::validateSequence(string const& _stepAbbreviations) { - bool insideLoop = false; + int8_t nestingLevel = 0; for (char abbreviation: _stepAbbreviations) switch (abbreviation) { @@ -277,12 +279,12 @@ void OptimiserSuite::validateSequence(string const& _stepAbbreviations) case '\n': break; case '[': - assertThrow(!insideLoop, OptimizerException, "Nested brackets are not supported"); - insideLoop = true; + assertThrow(nestingLevel < numeric_limits::max(), OptimizerException, "Brackets nested too deep"); + nestingLevel++; break; case ']': - assertThrow(insideLoop, OptimizerException, "Unbalanced brackets"); - insideLoop = false; + nestingLevel--; + assertThrow(nestingLevel >= 0, OptimizerException, "Unbalanced brackets"); break; default: { @@ -301,10 +303,9 @@ void OptimiserSuite::validateSequence(string const& _stepAbbreviations) OptimizerException, "'"s + abbreviation + "' is invalid in the current environment: " + *invalid ); - } } - assertThrow(!insideLoop, OptimizerException, "Unbalanced brackets"); + assertThrow(nestingLevel == 0, OptimizerException, "Unbalanced brackets"); } void OptimiserSuite::runSequence(string const& _stepAbbreviations, Block& _ast) From b415e94e191400c778fcf0c3b8785a3a91f0e5d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 6 Oct 2021 15:43:20 +0200 Subject: [PATCH 05/62] Reformat standard_optimizer command-line tests for readability --- .../standard_optimizer_invalid_detail_type/args | 1 + .../in.sol | 6 ++++++ .../input.json | 15 ++++----------- .../output.json | 13 ++++++++++++- .../standard_optimizer_invalid_details/args | 1 + .../standard_optimizer_invalid_details/in.sol | 6 ++++++ .../input.json | 15 ++++----------- .../output.json | 13 ++++++++++++- test/cmdlineTests/standard_optimizer_no_yul/args | 1 + .../standard_optimizer_no_yul/in.sol | 6 ++++++ .../standard_optimizer_no_yul/input.json | 13 ++++--------- .../standard_optimizer_no_yul/output.json | 10 +++++++++- test/cmdlineTests/standard_optimizer_yul/args | 1 + test/cmdlineTests/standard_optimizer_yul/in.sol | 6 ++++++ .../standard_optimizer_yul/input.json | 11 +++-------- .../standard_optimizer_yul/output.json | 10 +++++++++- .../standard_optimizer_yulDetails/args | 1 + .../standard_optimizer_yulDetails/in.sol | 6 ++++++ .../standard_optimizer_yulDetails/input.json | 16 +++++++--------- .../standard_optimizer_yulDetails/output.json | 10 +++++++++- .../standard_optimizer_yulDetails_no_object/args | 1 + .../in.sol | 6 ++++++ .../input.json | 16 +++++++--------- .../output.json | 13 ++++++++++++- .../args | 1 + .../in.sol | 6 ++++++ .../input.json | 11 +++-------- .../output.json | 10 +++++++++- .../args | 1 + .../in.sol | 6 ++++++ .../input.json | 11 +++-------- .../output.json | 13 ++++++++++++- .../args | 1 + .../in.sol | 6 ++++++ .../input.json | 11 +++-------- .../output.json | 13 ++++++++++++- .../args | 1 + .../in.sol | 6 ++++++ .../input.json | 11 +++-------- .../output.json | 13 ++++++++++++- .../args | 1 + .../in.sol | 6 ++++++ .../input.json | 11 +++-------- .../output.json | 13 ++++++++++++- .../args | 1 + .../in.sol | 6 ++++++ .../input.json | 14 ++++---------- .../output.json | 13 ++++++++++++- 48 files changed, 264 insertions(+), 119 deletions(-) create mode 100644 test/cmdlineTests/standard_optimizer_invalid_detail_type/args create mode 100644 test/cmdlineTests/standard_optimizer_invalid_detail_type/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_invalid_details/args create mode 100644 test/cmdlineTests/standard_optimizer_invalid_details/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_no_yul/args create mode 100644 test/cmdlineTests/standard_optimizer_no_yul/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_yul/args create mode 100644 test/cmdlineTests/standard_optimizer_yul/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_no_object/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_no_object/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/in.sol create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_without_yul/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_without_yul/in.sol diff --git a/test/cmdlineTests/standard_optimizer_invalid_detail_type/args b/test/cmdlineTests/standard_optimizer_invalid_detail_type/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_invalid_detail_type/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_invalid_detail_type/in.sol b/test/cmdlineTests/standard_optimizer_invalid_detail_type/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_invalid_detail_type/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_invalid_detail_type/input.json b/test/cmdlineTests/standard_optimizer_invalid_detail_type/input.json index 5e90f6d98..5d65bb2e2 100644 --- a/test/cmdlineTests/standard_optimizer_invalid_detail_type/input.json +++ b/test/cmdlineTests/standard_optimizer_invalid_detail_type/input.json @@ -1,16 +1,9 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_invalid_detail_type/in.sol"]} }, - "settings": - { - "optimizer": { - "details": { "peephole": 7 } - } + "settings": { + "optimizer": {"details": {"peephole": 7}} } } diff --git a/test/cmdlineTests/standard_optimizer_invalid_detail_type/output.json b/test/cmdlineTests/standard_optimizer_invalid_detail_type/output.json index 15a65e586..2601dea6c 100644 --- a/test/cmdlineTests/standard_optimizer_invalid_detail_type/output.json +++ b/test/cmdlineTests/standard_optimizer_invalid_detail_type/output.json @@ -1 +1,12 @@ -{"errors":[{"component":"general","formattedMessage":"\"settings.optimizer.details.peephole\" must be Boolean","message":"\"settings.optimizer.details.peephole\" must be Boolean","severity":"error","type":"JSONError"}]} +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "\"settings.optimizer.details.peephole\" must be Boolean", + "message": "\"settings.optimizer.details.peephole\" must be Boolean", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_optimizer_invalid_details/args b/test/cmdlineTests/standard_optimizer_invalid_details/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_invalid_details/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_invalid_details/in.sol b/test/cmdlineTests/standard_optimizer_invalid_details/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_invalid_details/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_invalid_details/input.json b/test/cmdlineTests/standard_optimizer_invalid_details/input.json index eecfbd5e5..dbab578d6 100644 --- a/test/cmdlineTests/standard_optimizer_invalid_details/input.json +++ b/test/cmdlineTests/standard_optimizer_invalid_details/input.json @@ -1,16 +1,9 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_invalid_details/in.sol"]} }, - "settings": - { - "optimizer": { - "details": { "notThere": true } - } + "settings": { + "optimizer": {"details": {"notThere": true}} } } diff --git a/test/cmdlineTests/standard_optimizer_invalid_details/output.json b/test/cmdlineTests/standard_optimizer_invalid_details/output.json index 20e62bc82..c7dfaf314 100644 --- a/test/cmdlineTests/standard_optimizer_invalid_details/output.json +++ b/test/cmdlineTests/standard_optimizer_invalid_details/output.json @@ -1 +1,12 @@ -{"errors":[{"component":"general","formattedMessage":"Unknown key \"notThere\"","message":"Unknown key \"notThere\"","severity":"error","type":"JSONError"}]} +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "Unknown key \"notThere\"", + "message": "Unknown key \"notThere\"", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_optimizer_no_yul/args b/test/cmdlineTests/standard_optimizer_no_yul/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_no_yul/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_no_yul/in.sol b/test/cmdlineTests/standard_optimizer_no_yul/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_no_yul/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_no_yul/input.json b/test/cmdlineTests/standard_optimizer_no_yul/input.json index a42299fbe..42ab767be 100644 --- a/test/cmdlineTests/standard_optimizer_no_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_no_yul/input.json @@ -1,17 +1,12 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_no_yul/in.sol"]} }, - "settings": - { + "settings": { "optimizer": { "enabled": true, - "details": { "yul": false } + "details": {"yul": false} } } } diff --git a/test/cmdlineTests/standard_optimizer_no_yul/output.json b/test/cmdlineTests/standard_optimizer_no_yul/output.json index 59b90c8cc..acf3b74ef 100644 --- a/test/cmdlineTests/standard_optimizer_no_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_no_yul/output.json @@ -1 +1,9 @@ -{"sources":{"A":{"id":0}}} +{ + "sources": + { + "A": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yul/args b/test/cmdlineTests/standard_optimizer_yul/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yul/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yul/in.sol b/test/cmdlineTests/standard_optimizer_yul/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yul/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yul/input.json b/test/cmdlineTests/standard_optimizer_yul/input.json index 5e81a6091..cf40ef970 100644 --- a/test/cmdlineTests/standard_optimizer_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_yul/input.json @@ -1,14 +1,9 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_yul/in.sol"]} }, - "settings": - { + "settings": { "optimizer": { "enabled": true } diff --git a/test/cmdlineTests/standard_optimizer_yul/output.json b/test/cmdlineTests/standard_optimizer_yul/output.json index 59b90c8cc..acf3b74ef 100644 --- a/test/cmdlineTests/standard_optimizer_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_yul/output.json @@ -1 +1,9 @@ -{"sources":{"A":{"id":0}}} +{ + "sources": + { + "A": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails/args b/test/cmdlineTests/standard_optimizer_yulDetails/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails/input.json b/test/cmdlineTests/standard_optimizer_yulDetails/input.json index 842468bca..6cdf504fd 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails/input.json @@ -1,16 +1,14 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails/in.sol"]} }, - "settings": - { + "settings": { "optimizer": { - "details": { "yul": true, "yulDetails": {} } + "details": { + "yul": true, + "yulDetails": {} + } } } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails/output.json b/test/cmdlineTests/standard_optimizer_yulDetails/output.json index 59b90c8cc..acf3b74ef 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails/output.json @@ -1 +1,9 @@ -{"sources":{"A":{"id":0}}} +{ + "sources": + { + "A": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/args b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/input.json index 2581aeb71..4aba68350 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/input.json @@ -1,16 +1,14 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_no_object/in.sol"]} }, - "settings": - { + "settings": { "optimizer": { - "details": { "yul": true, "yulDetails": 7 } + "details": { + "yul": true, + "yulDetails": 7 + } } } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/output.json index 35638adf0..86a0c8698 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_no_object/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_no_object/output.json @@ -1 +1,12 @@ -{"errors":[{"component":"general","formattedMessage":"\"settings.optimizer.details.yulDetails\" must be an object","message":"\"settings.optimizer.details.yulDetails\" must be an object","severity":"error","type":"JSONError"}]} +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "\"settings.optimizer.details.yulDetails\" must be an object", + "message": "\"settings.optimizer.details.yulDetails\" must be an object", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/args b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/input.json index 0dcdab6c2..584b8bf83 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/input.json @@ -1,14 +1,9 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps/in.sol"]} }, - "settings": - { + "settings": { "optimizer": { "details": { "yul": true, diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/output.json index 59b90c8cc..acf3b74ef 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps/output.json @@ -1 +1,9 @@ -{"sources":{"A":{"id":0}}} +{ + "sources": + { + "A": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/args b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/input.json index 427566764..48de0cce3 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/input.json @@ -1,14 +1,9 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/in.sol"]} }, - "settings": - { + "settings": { "optimizer": { "details": { "yul": true, diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/output.json index 84711c002..d4f6ef3a7 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/output.json @@ -1 +1,12 @@ -{"errors":[{"component":"general","formattedMessage":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": 'b' is not a valid step abbreviation","message":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": 'b' is not a valid step abbreviation","severity":"error","type":"JSONError"}]} +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": 'b' is not a valid step abbreviation", + "message": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": 'b' is not a valid step abbreviation", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/args b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/input.json index 851e132e8..881470ab5 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/input.json @@ -1,14 +1,9 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/in.sol"]} }, - "settings": - { + "settings": { "optimizer": { "details": { "yul": true, diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/output.json index 409fd755f..b2bc6b7d5 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/output.json @@ -1 +1,12 @@ -{"errors":[{"component":"general","formattedMessage":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Nested brackets are not supported","message":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Nested brackets are not supported","severity":"error","type":"JSONError"}]} +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Nested brackets are not supported", + "message": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Nested brackets are not supported", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/args b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/input.json index 11bc9ca62..e6f2abaa2 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/input.json @@ -1,14 +1,9 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_type/in.sol"]} }, - "settings": - { + "settings": { "optimizer": { "details": { "yul": true, diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/output.json index d18de5299..d6f9a9df8 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_type/output.json @@ -1 +1,12 @@ -{"errors":[{"component":"general","formattedMessage":"\"settings.optimizer.details.optimizerSteps\" must be a string","message":"\"settings.optimizer.details.optimizerSteps\" must be a string","severity":"error","type":"JSONError"}]} +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "\"settings.optimizer.details.optimizerSteps\" must be a string", + "message": "\"settings.optimizer.details.optimizerSteps\" must be a string", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/args b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/input.json index 79c52e6dd..ddfb37678 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/input.json @@ -1,14 +1,9 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/in.sol"]} }, - "settings": - { + "settings": { "optimizer": { "details": { "yul": true, diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/output.json index d1843709b..316529b0d 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/output.json @@ -1 +1,12 @@ -{"errors":[{"component":"general","formattedMessage":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets","message":"Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets","severity":"error","type":"JSONError"}]} +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets", + "message": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/args b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/input.json index cac3c068b..abd8cc0c8 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/input.json @@ -1,16 +1,10 @@ { "language": "Solidity", - "sources": - { - "A": - { - "content": "//SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; contract C { function f() public pure {} }" - } + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_without_yul/in.sol"]} }, - "settings": - { - "optimizer": { - "details": { "yulDetails": 7 } + "settings": { + "optimizer": {"details": {"yulDetails": 7} } } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/output.json index c44794cc1..4e6d7b6f4 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_without_yul/output.json @@ -1 +1,12 @@ -{"errors":[{"component":"general","formattedMessage":"\"Providing yulDetails requires Yul optimizer to be enabled.","message":"\"Providing yulDetails requires Yul optimizer to be enabled.","severity":"error","type":"JSONError"}]} +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "\"Providing yulDetails requires Yul optimizer to be enabled.", + "message": "\"Providing yulDetails requires Yul optimizer to be enabled.", + "severity": "error", + "type": "JSONError" + } + ] +} From 2fb8f1be5bd1869402177ac3db998681bc1e91e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 6 Oct 2021 16:44:29 +0200 Subject: [PATCH 06/62] OptimiserSuite: Use string_view instead of string for step sequences --- libyul/optimiser/Suite.cpp | 29 +++++++++++++---------------- libyul/optimiser/Suite.h | 7 ++++--- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 80b73f1cb..a77fd8ef9 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -89,7 +89,7 @@ void OptimiserSuite::run( GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, - string const& _optimisationSequence, + string_view _optimisationSequence, optional _expectedExecutionsPerDeployment, set const& _externallyUsedIdentifiers ) @@ -269,7 +269,7 @@ map const& OptimiserSuite::stepAbbreviationToNameMap() return lookupTable; } -void OptimiserSuite::validateSequence(string const& _stepAbbreviations) +void OptimiserSuite::validateSequence(string_view _stepAbbreviations) { int8_t nestingLevel = 0; for (char abbreviation: _stepAbbreviations) @@ -308,19 +308,16 @@ void OptimiserSuite::validateSequence(string const& _stepAbbreviations) assertThrow(nestingLevel == 0, OptimizerException, "Unbalanced brackets"); } -void OptimiserSuite::runSequence(string const& _stepAbbreviations, Block& _ast) +void OptimiserSuite::runSequence(string_view _stepAbbreviations, Block& _ast) { validateSequence(_stepAbbreviations); - string input = _stepAbbreviations; - ranges::actions::remove(input, ' '); - ranges::actions::remove(input, '\n'); - - auto abbreviationsToSteps = [](string const& _sequence) -> vector + auto abbreviationsToSteps = [](string_view _sequence) -> vector { vector steps; for (char abbreviation: _sequence) - steps.emplace_back(stepAbbreviationToNameMap().at(abbreviation)); + if (abbreviation != ' ' && abbreviation != '\n') + steps.emplace_back(stepAbbreviationToNameMap().at(abbreviation)); return steps; }; @@ -328,17 +325,17 @@ void OptimiserSuite::runSequence(string const& _stepAbbreviations, Block& _ast) // `aaa` or `[bbb]` can be empty. For example we consider a sequence like `fgo[aaf]Oo` to have // four segments, the last of which is an empty bracket. size_t currentPairStart = 0; - while (currentPairStart < input.size()) + while (currentPairStart < _stepAbbreviations.size()) { - size_t openingBracket = input.find('[', currentPairStart); - size_t closingBracket = input.find(']', openingBracket); - size_t firstCharInside = (openingBracket == string::npos ? input.size() : openingBracket + 1); + size_t openingBracket = _stepAbbreviations.find('[', currentPairStart); + size_t closingBracket = _stepAbbreviations.find(']', openingBracket); + size_t firstCharInside = (openingBracket == string::npos ? _stepAbbreviations.size() : openingBracket + 1); yulAssert((openingBracket == string::npos) == (closingBracket == string::npos), ""); - runSequence(abbreviationsToSteps(input.substr(currentPairStart, openingBracket - currentPairStart)), _ast); - runSequenceUntilStable(abbreviationsToSteps(input.substr(firstCharInside, closingBracket - firstCharInside)), _ast); + runSequence(abbreviationsToSteps(_stepAbbreviations.substr(currentPairStart, openingBracket - currentPairStart)), _ast); + runSequenceUntilStable(abbreviationsToSteps(_stepAbbreviations.substr(firstCharInside, closingBracket - firstCharInside)), _ast); - currentPairStart = (closingBracket == string::npos ? input.size() : closingBracket + 1); + currentPairStart = (closingBracket == string::npos ? _stepAbbreviations.size() : closingBracket + 1); } } diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index fa7b06bd0..062d76954 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -29,6 +29,7 @@ #include #include +#include #include namespace solidity::yul @@ -64,17 +65,17 @@ public: GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, - std::string const& _optimisationSequence, + std::string_view _optimisationSequence, std::optional _expectedExecutionsPerDeployment, std::set const& _externallyUsedIdentifiers = {} ); /// Ensures that specified sequence of step abbreviations is well-formed and can be executed. /// @throw OptimizerException if the sequence is invalid - static void validateSequence(std::string const& _stepAbbreviations); + static void validateSequence(std::string_view _stepAbbreviations); void runSequence(std::vector const& _steps, Block& _ast); - void runSequence(std::string const& _stepAbbreviations, Block& _ast); + void runSequence(std::string_view _stepAbbreviations, Block& _ast); void runSequenceUntilStable( std::vector const& _steps, Block& _ast, From 620ec47efb12e0b2a1ca49e8725a6e8c43e51a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 6 Oct 2021 16:00:16 +0200 Subject: [PATCH 07/62] OptimizerSuite: Rewrite runSequence() with support for nested brackets --- Changelog.md | 2 + libyul/optimiser/Suite.cpp | 108 +++-- libyul/optimiser/Suite.h | 7 +- .../args | 0 .../in.sol | 0 .../input.json | 16 + .../output.json | 9 + .../args | 0 .../in.sol | 0 .../input.json | 16 + .../output.json | 4 +- .../args | 1 + .../in.sol | 6 + .../input.json | 4 +- .../output.json | 0 .../args | 1 + .../in.sol | 6 + .../input.json | 2 +- .../output.json | 12 + .../yul_optimizer_steps_invalid_nesting/args | 1 - .../yul_optimizer_steps_invalid_nesting/err | 1 - .../yul_optimizer_steps_nested_brackets/args | 1 + .../input.sol | 0 .../output | 433 ++++++++++++++++++ .../yul_optimizer_steps_nesting_too_deep/args | 1 + .../yul_optimizer_steps_nesting_too_deep/err | 1 + .../exit | 0 .../input.sol | 0 .../args | 1 + .../err | 0 .../exit | 0 .../input.sol | 7 + .../args | 0 .../err | 1 + .../exit | 1 + .../input.sol | 7 + 36 files changed, 602 insertions(+), 47 deletions(-) rename test/cmdlineTests/{standard_optimizer_yulDetails_optimiserSteps_invalid_nesting => standard_optimizer_yulDetails_optimiserSteps_nested_brackets}/args (100%) rename test/cmdlineTests/{standard_optimizer_yulDetails_optimiserSteps_invalid_nesting => standard_optimizer_yulDetails_optimiserSteps_nested_brackets}/in.sol (100%) create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/input.json create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/output.json rename test/cmdlineTests/{standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket => standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep}/args (100%) rename test/cmdlineTests/{standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket => standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep}/in.sol (100%) create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/input.json rename test/cmdlineTests/{standard_optimizer_yulDetails_optimiserSteps_invalid_nesting => standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep}/output.json (62%) create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/in.sol rename test/cmdlineTests/{standard_optimizer_yulDetails_optimiserSteps_invalid_nesting => standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket}/input.json (53%) rename test/cmdlineTests/{standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket => standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket}/output.json (100%) create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/args create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/in.sol rename test/cmdlineTests/{standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket => standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket}/input.json (87%) create mode 100644 test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/output.json delete mode 100644 test/cmdlineTests/yul_optimizer_steps_invalid_nesting/args delete mode 100644 test/cmdlineTests/yul_optimizer_steps_invalid_nesting/err create mode 100644 test/cmdlineTests/yul_optimizer_steps_nested_brackets/args rename test/cmdlineTests/{yul_optimizer_steps_invalid_nesting => yul_optimizer_steps_nested_brackets}/input.sol (100%) create mode 100644 test/cmdlineTests/yul_optimizer_steps_nested_brackets/output create mode 100644 test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/args create mode 100644 test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/err rename test/cmdlineTests/{yul_optimizer_steps_invalid_nesting => yul_optimizer_steps_nesting_too_deep}/exit (100%) rename test/cmdlineTests/{yul_optimizer_steps_unbalanced_bracket => yul_optimizer_steps_nesting_too_deep}/input.sol (100%) create mode 100644 test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/args rename test/cmdlineTests/{yul_optimizer_steps_unbalanced_bracket => yul_optimizer_steps_unbalanced_closing_bracket}/err (100%) rename test/cmdlineTests/{yul_optimizer_steps_unbalanced_bracket => yul_optimizer_steps_unbalanced_closing_bracket}/exit (100%) create mode 100644 test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/input.sol rename test/cmdlineTests/{yul_optimizer_steps_unbalanced_bracket => yul_optimizer_steps_unbalanced_opening_bracket}/args (100%) create mode 100644 test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/err create mode 100644 test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/exit create mode 100644 test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/input.sol diff --git a/Changelog.md b/Changelog.md index 74e20d4b8..058ecc2e0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,7 +5,9 @@ Language Features: Compiler Features: + * Commandline Interface: Accept nested brackets in step sequences passed to ``--yul-optimizations``. * SMTChecker: Output values for ``block.*``, ``msg.*`` and ``tx.*`` variables that are present in the called functions. + * Standard JSON: Accept nested brackets in step sequences passed to ``settings.optimizer.details.yulDetails.optimizerSteps``. Bugfixes: diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index a77fd8ef9..5525e17d2 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -79,6 +79,7 @@ #include #include +#include using namespace std; using namespace solidity; @@ -308,10 +309,50 @@ void OptimiserSuite::validateSequence(string_view _stepAbbreviations) assertThrow(nestingLevel == 0, OptimizerException, "Unbalanced brackets"); } -void OptimiserSuite::runSequence(string_view _stepAbbreviations, Block& _ast) +void OptimiserSuite::runSequence(string_view _stepAbbreviations, Block& _ast, bool _repeatUntilStable) { validateSequence(_stepAbbreviations); + // This splits 'aaa[bbb]ccc...' into 'aaa' and '[bbb]ccc...'. + auto extractNonNestedPrefix = [](string_view _tail) -> tuple + { + for (size_t i = 0; i < _tail.size(); ++i) + { + yulAssert(_tail[i] != ']'); + if (_tail[i] == '[') + return {_tail.substr(0, i), _tail.substr(i)}; + } + return {_tail, {}}; + }; + + // This splits '[bbb]ccc...' into 'bbb' and 'ccc...'. + auto extractBracketContent = [](string_view _tail) -> tuple + { + yulAssert(!_tail.empty() && _tail[0] == '['); + + size_t contentLength = 0; + int8_t nestingLevel = 1; + for (char abbreviation: _tail.substr(1)) + { + if (abbreviation == '[') + { + yulAssert(nestingLevel < numeric_limits::max()); + ++nestingLevel; + } + else if (abbreviation == ']') + { + --nestingLevel; + if (nestingLevel == 0) + break; + } + ++contentLength; + } + yulAssert(nestingLevel == 0); + yulAssert(_tail[contentLength + 1] == ']'); + + return {_tail.substr(1, contentLength), _tail.substr(contentLength + 2)}; + }; + auto abbreviationsToSteps = [](string_view _sequence) -> vector { vector steps; @@ -321,21 +362,41 @@ void OptimiserSuite::runSequence(string_view _stepAbbreviations, Block& _ast) return steps; }; - // The sequence has now been validated and must consist of pairs of segments that look like this: `aaa[bbb]` - // `aaa` or `[bbb]` can be empty. For example we consider a sequence like `fgo[aaf]Oo` to have - // four segments, the last of which is an empty bracket. - size_t currentPairStart = 0; - while (currentPairStart < _stepAbbreviations.size()) + vector> subsequences; + string_view tail = _stepAbbreviations; + while (!tail.empty()) { - size_t openingBracket = _stepAbbreviations.find('[', currentPairStart); - size_t closingBracket = _stepAbbreviations.find(']', openingBracket); - size_t firstCharInside = (openingBracket == string::npos ? _stepAbbreviations.size() : openingBracket + 1); - yulAssert((openingBracket == string::npos) == (closingBracket == string::npos), ""); + string_view subsequence; + tie(subsequence, tail) = extractNonNestedPrefix(tail); + if (subsequence.size() > 0) + subsequences.push_back({subsequence, false}); - runSequence(abbreviationsToSteps(_stepAbbreviations.substr(currentPairStart, openingBracket - currentPairStart)), _ast); - runSequenceUntilStable(abbreviationsToSteps(_stepAbbreviations.substr(firstCharInside, closingBracket - firstCharInside)), _ast); + if (tail.empty()) + break; - currentPairStart = (closingBracket == string::npos ? _stepAbbreviations.size() : closingBracket + 1); + tie(subsequence, tail) = extractBracketContent(tail); + if (subsequence.size() > 0) + subsequences.push_back({subsequence, true}); + } + + size_t codeSize = 0; + for (size_t round = 0; round < MaxRounds; ++round) + { + for (auto const& [subsequence, repeat]: subsequences) + { + if (repeat) + runSequence(subsequence, _ast, true); + else + runSequence(abbreviationsToSteps(subsequence), _ast); + } + + if (!_repeatUntilStable) + break; + + size_t newSize = CodeSize::codeSizeIncludingFunctions(_ast); + if (newSize == codeSize) + break; + codeSize = newSize; } } @@ -363,24 +424,3 @@ void OptimiserSuite::runSequence(std::vector const& _steps, Block& _ast) } } } - -void OptimiserSuite::runSequenceUntilStable( - std::vector const& _steps, - Block& _ast, - size_t maxRounds -) -{ - if (_steps.empty()) - return; - - size_t codeSize = 0; - for (size_t rounds = 0; rounds < maxRounds; ++rounds) - { - size_t newSize = CodeSize::codeSizeIncludingFunctions(_ast); - if (newSize == codeSize) - break; - codeSize = newSize; - - runSequence(_steps, _ast); - } -} diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 062d76954..9b38ce542 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -75,12 +75,7 @@ public: static void validateSequence(std::string_view _stepAbbreviations); void runSequence(std::vector const& _steps, Block& _ast); - void runSequence(std::string_view _stepAbbreviations, Block& _ast); - void runSequenceUntilStable( - std::vector const& _steps, - Block& _ast, - size_t maxRounds = MaxRounds - ); + void runSequence(std::string_view _stepAbbreviations, Block& _ast, bool _repeatUntilStable = false); static std::map> const& allSteps(); static std::map const& stepNameToAbbreviationMap(); diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/args b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/args similarity index 100% rename from test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/args rename to test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/args diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/in.sol similarity index 100% rename from test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/in.sol rename to test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/in.sol diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/input.json new file mode 100644 index 000000000..2baf7a723 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/input.json @@ -0,0 +1,16 @@ +{ + "language": "Solidity", + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_nested_brackets/in.sol"]} + }, + "settings": { + "optimizer": { + "details": { + "yul": true, + "yulDetails": { + "optimizerSteps": "a[[a][[aa]aa[aa]][]]aaa[aa[aa[aa]]]a[a][a][a]a[a]" + } + } + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/output.json new file mode 100644 index 000000000..acf3b74ef --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nested_brackets/output.json @@ -0,0 +1,9 @@ +{ + "sources": + { + "A": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/args b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/args similarity index 100% rename from test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/args rename to test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/args diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/in.sol similarity index 100% rename from test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/in.sol rename to test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/in.sol diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/input.json new file mode 100644 index 000000000..1c055d915 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/input.json @@ -0,0 +1,16 @@ +{ + "language": "Solidity", + "sources": { + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/in.sol"]} + }, + "settings": { + "optimizer": { + "details": { + "yul": true, + "yulDetails": { + "optimizerSteps": "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[a]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" + } + } + } + } +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/output.json similarity index 62% rename from test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/output.json rename to test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/output.json index b2bc6b7d5..e06e14205 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/output.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/output.json @@ -3,8 +3,8 @@ [ { "component": "general", - "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Nested brackets are not supported", - "message": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Nested brackets are not supported", + "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Brackets nested too deep", + "message": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Brackets nested too deep", "severity": "error", "type": "JSONError" } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/args b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/input.json similarity index 53% rename from test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/input.json rename to test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/input.json index 881470ab5..e3cd50027 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/input.json @@ -1,14 +1,14 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_invalid_nesting/in.sol"]} + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/in.sol"]} }, "settings": { "optimizer": { "details": { "yul": true, "yulDetails": { - "optimizerSteps": "a[a][aa[aa]]a" + "optimizerSteps": "a]a][" } } } diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/output.json similarity index 100% rename from test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/output.json rename to test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/output.json diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/args b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/in.sol b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/in.sol new file mode 100644 index 000000000..9e5350072 --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C { + function f() public pure {} +} diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/input.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/input.json similarity index 87% rename from test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/input.json rename to test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/input.json index ddfb37678..6cf7a2334 100644 --- a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/input.json +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/input.json @@ -1,7 +1,7 @@ { "language": "Solidity", "sources": { - "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_unbalanced_bracket/in.sol"]} + "A": {"urls": ["standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/in.sol"]} }, "settings": { "optimizer": { diff --git a/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/output.json b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/output.json new file mode 100644 index 000000000..316529b0d --- /dev/null +++ b/test/cmdlineTests/standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets", + "message": "Invalid optimizer step sequence in \"settings.optimizer.details.optimizerSteps\": Unbalanced brackets", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/yul_optimizer_steps_invalid_nesting/args b/test/cmdlineTests/yul_optimizer_steps_invalid_nesting/args deleted file mode 100644 index 724fe4724..000000000 --- a/test/cmdlineTests/yul_optimizer_steps_invalid_nesting/args +++ /dev/null @@ -1 +0,0 @@ ---ir-optimized --optimize --yul-optimizations a[a][aa[aa]]a diff --git a/test/cmdlineTests/yul_optimizer_steps_invalid_nesting/err b/test/cmdlineTests/yul_optimizer_steps_invalid_nesting/err deleted file mode 100644 index 2f6d9ff47..000000000 --- a/test/cmdlineTests/yul_optimizer_steps_invalid_nesting/err +++ /dev/null @@ -1 +0,0 @@ -Invalid optimizer step sequence in --yul-optimizations: Nested brackets are not supported diff --git a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/args b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/args new file mode 100644 index 000000000..4b536761f --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/args @@ -0,0 +1 @@ +--ir-optimized --optimize --yul-optimizations a[[a][[aa]aa[aa]][]]aaa[aa[aa[aa]]]a[a][a][a]a[a] diff --git a/test/cmdlineTests/yul_optimizer_steps_invalid_nesting/input.sol b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/input.sol similarity index 100% rename from test/cmdlineTests/yul_optimizer_steps_invalid_nesting/input.sol rename to test/cmdlineTests/yul_optimizer_steps_nested_brackets/input.sol diff --git a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output new file mode 100644 index 000000000..d4c026105 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output @@ -0,0 +1,433 @@ +Optimized IR: +/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + +/// @use-src 0:"yul_optimizer_steps_nested_brackets/input.sol" +object "C_6" { + code { + { + /// @src 0:60:103 "contract C..." + mstore(64, 128) + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + constructor_C() + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + return(_1, datasize("C_6_deployed")) + } + function allocate_unbounded() -> memPtr + { + let memPtr_1 := mload(64) + let memPtr_2 := memPtr_1 + let memPtr_3 := memPtr_1 + let memPtr_4 := memPtr_1 + let memPtr_5 := memPtr_1 + let memPtr_6 := memPtr_1 + let memPtr_7 := memPtr_1 + let memPtr_8 := memPtr_1 + let memPtr_9 := memPtr_1 + let memPtr_10 := memPtr_1 + let memPtr_11 := memPtr_1 + let memPtr_12 := memPtr_1 + let memPtr_13 := memPtr_1 + let memPtr_14 := memPtr_1 + let memPtr_15 := memPtr_1 + let memPtr_16 := memPtr_1 + let memPtr_17 := memPtr_1 + let memPtr_18 := memPtr_1 + let memPtr_19 := memPtr_1 + let memPtr_20 := memPtr_1 + let memPtr_21 := memPtr_1 + let memPtr_22 := memPtr_1 + let memPtr_23 := memPtr_1 + let memPtr_24 := memPtr_1 + let memPtr_25 := memPtr_1 + let memPtr_26 := memPtr_1 + let memPtr_27 := memPtr_1 + let memPtr_28 := memPtr_1 + let memPtr_29 := memPtr_1 + let memPtr_30 := memPtr_1 + let memPtr_31 := memPtr_1 + let memPtr_32 := memPtr_1 + let memPtr_33 := memPtr_1 + let memPtr_34 := memPtr_1 + let memPtr_35 := memPtr_1 + let memPtr_36 := memPtr_1 + let memPtr_37 := memPtr_1 + let memPtr_38 := memPtr_1 + let memPtr_39 := memPtr_1 + let memPtr_40 := memPtr_1 + let memPtr_41 := memPtr_1 + let memPtr_42 := memPtr_1 + let memPtr_43 := memPtr_1 + let memPtr_44 := memPtr_1 + let memPtr_45 := memPtr_1 + let memPtr_46 := memPtr_1 + let memPtr_47 := memPtr_1 + let memPtr_48 := memPtr_1 + let memPtr_49 := memPtr_1 + let memPtr_50 := memPtr_1 + let memPtr_51 := memPtr_1 + let memPtr_52 := memPtr_1 + let memPtr_53 := memPtr_1 + let memPtr_54 := memPtr_1 + let memPtr_55 := memPtr_1 + let memPtr_56 := memPtr_1 + let memPtr_57 := memPtr_1 + let memPtr_58 := memPtr_1 + let memPtr_59 := memPtr_1 + let memPtr_60 := memPtr_1 + let memPtr_61 := memPtr_1 + let memPtr_62 := memPtr_1 + let memPtr_63 := memPtr_1 + let memPtr_64 := memPtr_1 + let memPtr_65 := memPtr_1 + let memPtr_66 := memPtr_1 + let memPtr_67 := memPtr_1 + let memPtr_68 := memPtr_1 + let memPtr_69 := memPtr_1 + let memPtr_70 := memPtr_1 + let memPtr_71 := memPtr_1 + let memPtr_72 := memPtr_1 + let memPtr_73 := memPtr_1 + let memPtr_74 := memPtr_1 + let memPtr_75 := memPtr_1 + let memPtr_76 := memPtr_1 + let memPtr_77 := memPtr_1 + let memPtr_78 := memPtr_1 + let memPtr_79 := memPtr_1 + let memPtr_80 := memPtr_1 + let memPtr_81 := memPtr_1 + let memPtr_82 := memPtr_1 + let memPtr_83 := memPtr_1 + let memPtr_84 := memPtr_1 + let memPtr_85 := memPtr_1 + let memPtr_86 := memPtr_1 + memPtr := memPtr_1 + } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function constructor_C() + { } + } + /// @use-src 0:"yul_optimizer_steps_nested_brackets/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:103 "contract C..." + mstore(64, 128) + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_unsigned(calldataload(0)) + if eq(0x26121ff0, selector) + { + if callvalue() + { + revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + } + abi_decode(4, calldatasize()) + fun_f() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple(memPos) + return(memPos, sub(memEnd, memPos)) + } + } + pop(iszero(calldatasize())) + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + } + function shift_right_unsigned(value) -> newValue + { + let newValue_1 := shr(224, value) + let newValue_2 := newValue_1 + let newValue_3 := newValue_1 + let newValue_4 := newValue_1 + let newValue_5 := newValue_1 + let newValue_6 := newValue_1 + let newValue_7 := newValue_1 + let newValue_8 := newValue_1 + let newValue_9 := newValue_1 + let newValue_10 := newValue_1 + let newValue_11 := newValue_1 + let newValue_12 := newValue_1 + let newValue_13 := newValue_1 + let newValue_14 := newValue_1 + let newValue_15 := newValue_1 + let newValue_16 := newValue_1 + let newValue_17 := newValue_1 + let newValue_18 := newValue_1 + let newValue_19 := newValue_1 + let newValue_20 := newValue_1 + let newValue_21 := newValue_1 + let newValue_22 := newValue_1 + let newValue_23 := newValue_1 + let newValue_24 := newValue_1 + let newValue_25 := newValue_1 + let newValue_26 := newValue_1 + let newValue_27 := newValue_1 + let newValue_28 := newValue_1 + let newValue_29 := newValue_1 + let newValue_30 := newValue_1 + let newValue_31 := newValue_1 + let newValue_32 := newValue_1 + let newValue_33 := newValue_1 + let newValue_34 := newValue_1 + let newValue_35 := newValue_1 + let newValue_36 := newValue_1 + let newValue_37 := newValue_1 + let newValue_38 := newValue_1 + let newValue_39 := newValue_1 + let newValue_40 := newValue_1 + let newValue_41 := newValue_1 + let newValue_42 := newValue_1 + let newValue_43 := newValue_1 + let newValue_44 := newValue_1 + let newValue_45 := newValue_1 + let newValue_46 := newValue_1 + let newValue_47 := newValue_1 + let newValue_48 := newValue_1 + let newValue_49 := newValue_1 + let newValue_50 := newValue_1 + let newValue_51 := newValue_1 + let newValue_52 := newValue_1 + let newValue_53 := newValue_1 + let newValue_54 := newValue_1 + let newValue_55 := newValue_1 + let newValue_56 := newValue_1 + let newValue_57 := newValue_1 + let newValue_58 := newValue_1 + let newValue_59 := newValue_1 + let newValue_60 := newValue_1 + let newValue_61 := newValue_1 + let newValue_62 := newValue_1 + let newValue_63 := newValue_1 + let newValue_64 := newValue_1 + let newValue_65 := newValue_1 + let newValue_66 := newValue_1 + let newValue_67 := newValue_1 + let newValue_68 := newValue_1 + let newValue_69 := newValue_1 + let newValue_70 := newValue_1 + let newValue_71 := newValue_1 + let newValue_72 := newValue_1 + let newValue_73 := newValue_1 + let newValue_74 := newValue_1 + let newValue_75 := newValue_1 + let newValue_76 := newValue_1 + let newValue_77 := newValue_1 + let newValue_78 := newValue_1 + let newValue_79 := newValue_1 + let newValue_80 := newValue_1 + let newValue_81 := newValue_1 + let newValue_82 := newValue_1 + let newValue_83 := newValue_1 + let newValue_84 := newValue_1 + let newValue_85 := newValue_1 + let newValue_86 := newValue_1 + newValue := newValue_1 + } + function allocate_unbounded() -> memPtr + { + let memPtr_1 := mload(64) + let memPtr_2 := memPtr_1 + let memPtr_3 := memPtr_1 + let memPtr_4 := memPtr_1 + let memPtr_5 := memPtr_1 + let memPtr_6 := memPtr_1 + let memPtr_7 := memPtr_1 + let memPtr_8 := memPtr_1 + let memPtr_9 := memPtr_1 + let memPtr_10 := memPtr_1 + let memPtr_11 := memPtr_1 + let memPtr_12 := memPtr_1 + let memPtr_13 := memPtr_1 + let memPtr_14 := memPtr_1 + let memPtr_15 := memPtr_1 + let memPtr_16 := memPtr_1 + let memPtr_17 := memPtr_1 + let memPtr_18 := memPtr_1 + let memPtr_19 := memPtr_1 + let memPtr_20 := memPtr_1 + let memPtr_21 := memPtr_1 + let memPtr_22 := memPtr_1 + let memPtr_23 := memPtr_1 + let memPtr_24 := memPtr_1 + let memPtr_25 := memPtr_1 + let memPtr_26 := memPtr_1 + let memPtr_27 := memPtr_1 + let memPtr_28 := memPtr_1 + let memPtr_29 := memPtr_1 + let memPtr_30 := memPtr_1 + let memPtr_31 := memPtr_1 + let memPtr_32 := memPtr_1 + let memPtr_33 := memPtr_1 + let memPtr_34 := memPtr_1 + let memPtr_35 := memPtr_1 + let memPtr_36 := memPtr_1 + let memPtr_37 := memPtr_1 + let memPtr_38 := memPtr_1 + let memPtr_39 := memPtr_1 + let memPtr_40 := memPtr_1 + let memPtr_41 := memPtr_1 + let memPtr_42 := memPtr_1 + let memPtr_43 := memPtr_1 + let memPtr_44 := memPtr_1 + let memPtr_45 := memPtr_1 + let memPtr_46 := memPtr_1 + let memPtr_47 := memPtr_1 + let memPtr_48 := memPtr_1 + let memPtr_49 := memPtr_1 + let memPtr_50 := memPtr_1 + let memPtr_51 := memPtr_1 + let memPtr_52 := memPtr_1 + let memPtr_53 := memPtr_1 + let memPtr_54 := memPtr_1 + let memPtr_55 := memPtr_1 + let memPtr_56 := memPtr_1 + let memPtr_57 := memPtr_1 + let memPtr_58 := memPtr_1 + let memPtr_59 := memPtr_1 + let memPtr_60 := memPtr_1 + let memPtr_61 := memPtr_1 + let memPtr_62 := memPtr_1 + let memPtr_63 := memPtr_1 + let memPtr_64 := memPtr_1 + let memPtr_65 := memPtr_1 + let memPtr_66 := memPtr_1 + let memPtr_67 := memPtr_1 + let memPtr_68 := memPtr_1 + let memPtr_69 := memPtr_1 + let memPtr_70 := memPtr_1 + let memPtr_71 := memPtr_1 + let memPtr_72 := memPtr_1 + let memPtr_73 := memPtr_1 + let memPtr_74 := memPtr_1 + let memPtr_75 := memPtr_1 + let memPtr_76 := memPtr_1 + let memPtr_77 := memPtr_1 + let memPtr_78 := memPtr_1 + let memPtr_79 := memPtr_1 + let memPtr_80 := memPtr_1 + let memPtr_81 := memPtr_1 + let memPtr_82 := memPtr_1 + let memPtr_83 := memPtr_1 + let memPtr_84 := memPtr_1 + let memPtr_85 := memPtr_1 + let memPtr_86 := memPtr_1 + memPtr := memPtr_1 + } + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() + { revert(0, 0) } + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + { revert(0, 0) } + function abi_decode(headStart, dataEnd) + { + if slt(sub(dataEnd, headStart), 0) + { + revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() + } + } + function abi_encode_tuple(headStart) -> tail + { + let tail_1 := add(headStart, 0) + let tail_2 := tail_1 + let tail_3 := tail_1 + let tail_4 := tail_1 + let tail_5 := tail_1 + let tail_6 := tail_1 + let tail_7 := tail_1 + let tail_8 := tail_1 + let tail_9 := tail_1 + let tail_10 := tail_1 + let tail_11 := tail_1 + let tail_12 := tail_1 + let tail_13 := tail_1 + let tail_14 := tail_1 + let tail_15 := tail_1 + let tail_16 := tail_1 + let tail_17 := tail_1 + let tail_18 := tail_1 + let tail_19 := tail_1 + let tail_20 := tail_1 + let tail_21 := tail_1 + let tail_22 := tail_1 + let tail_23 := tail_1 + let tail_24 := tail_1 + let tail_25 := tail_1 + let tail_26 := tail_1 + let tail_27 := tail_1 + let tail_28 := tail_1 + let tail_29 := tail_1 + let tail_30 := tail_1 + let tail_31 := tail_1 + let tail_32 := tail_1 + let tail_33 := tail_1 + let tail_34 := tail_1 + let tail_35 := tail_1 + let tail_36 := tail_1 + let tail_37 := tail_1 + let tail_38 := tail_1 + let tail_39 := tail_1 + let tail_40 := tail_1 + let tail_41 := tail_1 + let tail_42 := tail_1 + let tail_43 := tail_1 + let tail_44 := tail_1 + let tail_45 := tail_1 + let tail_46 := tail_1 + let tail_47 := tail_1 + let tail_48 := tail_1 + let tail_49 := tail_1 + let tail_50 := tail_1 + let tail_51 := tail_1 + let tail_52 := tail_1 + let tail_53 := tail_1 + let tail_54 := tail_1 + let tail_55 := tail_1 + let tail_56 := tail_1 + let tail_57 := tail_1 + let tail_58 := tail_1 + let tail_59 := tail_1 + let tail_60 := tail_1 + let tail_61 := tail_1 + let tail_62 := tail_1 + let tail_63 := tail_1 + let tail_64 := tail_1 + let tail_65 := tail_1 + let tail_66 := tail_1 + let tail_67 := tail_1 + let tail_68 := tail_1 + let tail_69 := tail_1 + let tail_70 := tail_1 + let tail_71 := tail_1 + let tail_72 := tail_1 + let tail_73 := tail_1 + let tail_74 := tail_1 + let tail_75 := tail_1 + let tail_76 := tail_1 + let tail_77 := tail_1 + let tail_78 := tail_1 + let tail_79 := tail_1 + let tail_80 := tail_1 + let tail_81 := tail_1 + let tail_82 := tail_1 + let tail_83 := tail_1 + let tail_84 := tail_1 + let tail_85 := tail_1 + let tail_86 := tail_1 + tail := tail_1 + } + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + { revert(0, 0) } + /// @ast-id 5 @src 0:74:101 "function f() public pure {}" + function fun_f() + { } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/args b/test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/args new file mode 100644 index 000000000..b2ff99d3f --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/args @@ -0,0 +1 @@ +--ir-optimized --optimize --yul-optimizations [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[a]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] diff --git a/test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/err b/test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/err new file mode 100644 index 000000000..c8dc9697e --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/err @@ -0,0 +1 @@ +Invalid optimizer step sequence in --yul-optimizations: Brackets nested too deep diff --git a/test/cmdlineTests/yul_optimizer_steps_invalid_nesting/exit b/test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/exit similarity index 100% rename from test/cmdlineTests/yul_optimizer_steps_invalid_nesting/exit rename to test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/exit diff --git a/test/cmdlineTests/yul_optimizer_steps_unbalanced_bracket/input.sol b/test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/input.sol similarity index 100% rename from test/cmdlineTests/yul_optimizer_steps_unbalanced_bracket/input.sol rename to test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/input.sol diff --git a/test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/args b/test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/args new file mode 100644 index 000000000..04933d213 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/args @@ -0,0 +1 @@ +--ir-optimized --optimize --yul-optimizations a]a][ diff --git a/test/cmdlineTests/yul_optimizer_steps_unbalanced_bracket/err b/test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/err similarity index 100% rename from test/cmdlineTests/yul_optimizer_steps_unbalanced_bracket/err rename to test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/err diff --git a/test/cmdlineTests/yul_optimizer_steps_unbalanced_bracket/exit b/test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/exit similarity index 100% rename from test/cmdlineTests/yul_optimizer_steps_unbalanced_bracket/exit rename to test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/exit diff --git a/test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/input.sol b/test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/input.sol new file mode 100644 index 000000000..6923ca702 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_unbalanced_closing_bracket/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C +{ + function f() public pure {} +} diff --git a/test/cmdlineTests/yul_optimizer_steps_unbalanced_bracket/args b/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/args similarity index 100% rename from test/cmdlineTests/yul_optimizer_steps_unbalanced_bracket/args rename to test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/args diff --git a/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/err b/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/err new file mode 100644 index 000000000..1da42b743 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/err @@ -0,0 +1 @@ +Invalid optimizer step sequence in --yul-optimizations: Unbalanced brackets diff --git a/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/exit b/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/input.sol b/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/input.sol new file mode 100644 index 000000000..6923ca702 --- /dev/null +++ b/test/cmdlineTests/yul_optimizer_steps_unbalanced_opening_bracket/input.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.0; + +contract C +{ + function f() public pure {} +} From b9b2c69d246235525fee6a97a6c49ff993b3cead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 4 Oct 2021 16:35:59 +0200 Subject: [PATCH 08/62] CommandLineParser: Validate compiler output selection --- Changelog.md | 1 + solc/CommandLineParser.cpp | 53 ++++++++++++++++++- solc/CommandLineParser.h | 2 + .../linker_mode_output_selection_invalid/args | 1 + .../linker_mode_output_selection_invalid/err | 1 + .../linker_mode_output_selection_invalid/exit | 1 + .../input.bin | 0 .../args | 1 + .../standard_cli_output_selection_invalid/err | 1 + .../exit | 1 + .../input.json | 0 .../strict_asm_output_selection_invalid/args | 1 + .../strict_asm_output_selection_invalid/err | 1 + .../strict_asm_output_selection_invalid/exit | 1 + .../input.yul | 0 test/cmdlineTests/yul_optimize_runs/args | 2 +- test/solc/CommandLineParser.cpp | 18 ------- 17 files changed, 64 insertions(+), 21 deletions(-) create mode 100644 test/cmdlineTests/linker_mode_output_selection_invalid/args create mode 100644 test/cmdlineTests/linker_mode_output_selection_invalid/err create mode 100644 test/cmdlineTests/linker_mode_output_selection_invalid/exit create mode 100644 test/cmdlineTests/linker_mode_output_selection_invalid/input.bin create mode 100644 test/cmdlineTests/standard_cli_output_selection_invalid/args create mode 100644 test/cmdlineTests/standard_cli_output_selection_invalid/err create mode 100644 test/cmdlineTests/standard_cli_output_selection_invalid/exit create mode 100644 test/cmdlineTests/standard_cli_output_selection_invalid/input.json create mode 100644 test/cmdlineTests/strict_asm_output_selection_invalid/args create mode 100644 test/cmdlineTests/strict_asm_output_selection_invalid/err create mode 100644 test/cmdlineTests/strict_asm_output_selection_invalid/exit create mode 100644 test/cmdlineTests/strict_asm_output_selection_invalid/input.yul diff --git a/Changelog.md b/Changelog.md index 74e20d4b8..173751636 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ Compiler Features: Bugfixes: * Commandline Interface: Fix extra newline character being appended to sources passed through standard input, affecting their hashes. + * Commandline Interface: Report output selection options unsupported by the selected input mode instead of ignoring them. * SMTChecker: Fix internal error in magic type access (``block``, ``msg``, ``tx``). * TypeChecker: Fix internal error when using user defined value types in public library functions. diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 26b8dd255..6c673c311 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -137,6 +137,14 @@ static set const g_metadataHashArgs g_strNone }; +static map const g_inputModeName = { + {InputMode::Compiler, "compiler"}, + {InputMode::CompilerWithASTImport, "compiler (AST import)"}, + {InputMode::Assembler, "assembler"}, + {InputMode::StandardJson, "standard JSON"}, + {InputMode::Linker, "linker"}, +}; + void CommandLineParser::printVersionAndExit() { sout() << @@ -460,6 +468,47 @@ bool CommandLineParser::parseLibraryOption(string const& _input) return true; } +bool CommandLineParser::parseOutputSelection() +{ + static auto outputSupported = [](InputMode _mode, string_view _outputName) + { + static set const compilerModeOutputs = + CompilerOutputs::componentMap() | + ranges::views::keys | + ranges::to(); + + switch (_mode) + { + case InputMode::Compiler: + case InputMode::CompilerWithASTImport: + return contains(compilerModeOutputs, _outputName); + case InputMode::Assembler: + case InputMode::StandardJson: + case InputMode::Linker: + return false; + } + + solAssert(false, ""); + }; + + for (auto&& [optionName, outputComponent]: CompilerOutputs::componentMap()) + m_options.compiler.outputs.*outputComponent = (m_args.count(optionName) > 0); + + vector unsupportedOutputs; + for (auto&& [optionName, outputComponent]: CompilerOutputs::componentMap()) + if (m_options.compiler.outputs.*outputComponent && !outputSupported(m_options.input.mode, optionName)) + unsupportedOutputs.push_back(optionName); + + if (!unsupportedOutputs.empty()) + { + serr() << "The following outputs are not supported in " << g_inputModeName.at(m_options.input.mode) << " mode: "; + serr() << joinOptionNames(unsupportedOutputs) << "."; + return false; + } + + return true; +} + po::options_description CommandLineParser::optionsDescription() { // Declare the supported options. @@ -930,8 +979,8 @@ bool CommandLineParser::processArgs() m_options.formatting.json.indent = m_args[g_strJsonIndent].as(); } - for (auto&& [optionName, outputComponent]: CompilerOutputs::componentMap()) - m_options.compiler.outputs.*outputComponent = (m_args.count(optionName) > 0); + if (!parseOutputSelection()) + return false; m_options.compiler.estimateGas = (m_args.count(g_strGas) > 0); diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 7e1266653..1f09ea993 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -286,6 +286,8 @@ private: /// @return false if there are any validation errors, true otherwise. bool parseLibraryOption(std::string const& _input); + bool parseOutputSelection(); + bool checkMutuallyExclusive(std::vector const& _optionNames); [[noreturn]] void printVersionAndExit(); [[noreturn]] void printLicenseAndExit(); diff --git a/test/cmdlineTests/linker_mode_output_selection_invalid/args b/test/cmdlineTests/linker_mode_output_selection_invalid/args new file mode 100644 index 000000000..ded0d6efc --- /dev/null +++ b/test/cmdlineTests/linker_mode_output_selection_invalid/args @@ -0,0 +1 @@ +--link --asm --asm-json --opcodes --bin --bin-runtime --abi --ir --ir-optimized --ewasm --hashes --userdoc --devdoc --metadata --storage-layout diff --git a/test/cmdlineTests/linker_mode_output_selection_invalid/err b/test/cmdlineTests/linker_mode_output_selection_invalid/err new file mode 100644 index 000000000..c84a12d97 --- /dev/null +++ b/test/cmdlineTests/linker_mode_output_selection_invalid/err @@ -0,0 +1 @@ +The following outputs are not supported in linker mode: --abi, --asm, --asm-json, --bin, --bin-runtime, --devdoc, --ewasm, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc. diff --git a/test/cmdlineTests/linker_mode_output_selection_invalid/exit b/test/cmdlineTests/linker_mode_output_selection_invalid/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/linker_mode_output_selection_invalid/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/linker_mode_output_selection_invalid/input.bin b/test/cmdlineTests/linker_mode_output_selection_invalid/input.bin new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/standard_cli_output_selection_invalid/args b/test/cmdlineTests/standard_cli_output_selection_invalid/args new file mode 100644 index 000000000..f2deb3847 --- /dev/null +++ b/test/cmdlineTests/standard_cli_output_selection_invalid/args @@ -0,0 +1 @@ +--ast-compact-json --asm --asm-json --opcodes --bin --bin-runtime --abi --ir --ir-optimized --ewasm --hashes --userdoc --devdoc --metadata --storage-layout diff --git a/test/cmdlineTests/standard_cli_output_selection_invalid/err b/test/cmdlineTests/standard_cli_output_selection_invalid/err new file mode 100644 index 000000000..d6ed4d572 --- /dev/null +++ b/test/cmdlineTests/standard_cli_output_selection_invalid/err @@ -0,0 +1 @@ +The following outputs are not supported in standard JSON mode: --abi, --asm, --asm-json, --ast-compact-json, --bin, --bin-runtime, --devdoc, --ewasm, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc. diff --git a/test/cmdlineTests/standard_cli_output_selection_invalid/exit b/test/cmdlineTests/standard_cli_output_selection_invalid/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/standard_cli_output_selection_invalid/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/standard_cli_output_selection_invalid/input.json b/test/cmdlineTests/standard_cli_output_selection_invalid/input.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/strict_asm_output_selection_invalid/args b/test/cmdlineTests/strict_asm_output_selection_invalid/args new file mode 100644 index 000000000..85814eb29 --- /dev/null +++ b/test/cmdlineTests/strict_asm_output_selection_invalid/args @@ -0,0 +1 @@ +--strict-assembly --asm --asm-json --opcodes --bin --bin-runtime --abi --ir --ir-optimized --ewasm --hashes --userdoc --devdoc --metadata --storage-layout diff --git a/test/cmdlineTests/strict_asm_output_selection_invalid/err b/test/cmdlineTests/strict_asm_output_selection_invalid/err new file mode 100644 index 000000000..736eb2c8a --- /dev/null +++ b/test/cmdlineTests/strict_asm_output_selection_invalid/err @@ -0,0 +1 @@ +The following outputs are not supported in assembler mode: --abi, --asm, --asm-json, --bin, --bin-runtime, --devdoc, --ewasm, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc. diff --git a/test/cmdlineTests/strict_asm_output_selection_invalid/exit b/test/cmdlineTests/strict_asm_output_selection_invalid/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/strict_asm_output_selection_invalid/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/strict_asm_output_selection_invalid/input.yul b/test/cmdlineTests/strict_asm_output_selection_invalid/input.yul new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/yul_optimize_runs/args b/test/cmdlineTests/yul_optimize_runs/args index b48e7aeed..033abe3bb 100644 --- a/test/cmdlineTests/yul_optimize_runs/args +++ b/test/cmdlineTests/yul_optimize_runs/args @@ -1 +1 @@ ---yul --yul-dialect evm --optimize --ir-optimized --optimize-runs 10000 +--yul --yul-dialect evm --optimize --optimize-runs 10000 diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 7b1dd375b..939850304 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -289,10 +289,6 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) "underflow," "divByZero", "--model-checker-timeout=5", // Ignored in assembly mode - - // Accepted but has no effect in assembly mode - "--ast-compact-json", "--asm", "--asm-json", "--opcodes", "--bin", "--bin-runtime", "--abi", - "--ir", "--ir-optimized", "--ewasm", "--hashes", "--userdoc", "--devdoc", "--metadata", "--storage-layout", }; commandLine += assemblyOptions; if (expectedLanguage == AssemblyStack::Language::StrictAssembly || expectedLanguage == AssemblyStack::Language::Ewasm) @@ -328,11 +324,6 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) }; expectedOptions.formatting.coloredOutput = false; expectedOptions.formatting.withErrorIds = true; - expectedOptions.compiler.outputs = { - true, true, true, true, true, - true, true, true, true, true, - true, true, true, true, true, - }; if (expectedLanguage == AssemblyStack::Language::StrictAssembly || expectedLanguage == AssemblyStack::Language::Ewasm) { expectedOptions.optimizer.enabled = true; @@ -388,10 +379,6 @@ BOOST_AUTO_TEST_CASE(standard_json_mode_options) "underflow," "divByZero", "--model-checker-timeout=5", // Ignored in Standard JSON mode - - // Accepted but has no effect in Standard JSON mode - "--ast-compact-json", "--asm", "--asm-json", "--opcodes", "--bin", "--bin-runtime", "--abi", - "--ir", "--ir-optimized", "--ewasm", "--hashes", "--userdoc", "--devdoc", "--metadata", "--storage-layout", }; CommandLineOptions expectedOptions; @@ -408,11 +395,6 @@ BOOST_AUTO_TEST_CASE(standard_json_mode_options) expectedOptions.formatting.json = JsonFormat {JsonFormat::Pretty, 1}; expectedOptions.formatting.coloredOutput = false; expectedOptions.formatting.withErrorIds = true; - expectedOptions.compiler.outputs = { - true, true, true, true, true, - true, true, true, true, true, - true, true, true, true, true, - }; expectedOptions.compiler.estimateGas = true; expectedOptions.compiler.combinedJsonRequests = CombinedJsonRequests{}; expectedOptions.compiler.combinedJsonRequests->abi = true; From 7b1a12ae4c294f38069e9af2a79666959eb2f6be Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Wed, 6 Oct 2021 18:00:07 -0600 Subject: [PATCH 09/62] Snap: update z3 --- snap/snapcraft.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 0826749ee..e462823e8 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -41,9 +41,9 @@ parts: source-tag: z3-4.8.4 plugin: make build-packages: [python3] - stage-packages: [libstdc++6] + stage-packages: [libstdc++6, libgomp1] override-build: | - python scripts/mk_make.py + python3 scripts/mk_make.py cd build make -j -l $(grep -c "^processor" /proc/cpuinfo) make install DESTDIR=$SNAPCRAFT_PART_INSTALL From 0043eca672e4389d345203507a6cf67b3afee0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 5 Oct 2021 16:32:03 +0200 Subject: [PATCH 10/62] Consistent indentation in doc config, templates and static files --- docs/_static/css/custom.css | 14 +++++++------- docs/_templates/layout.html | 6 +++--- docs/conf.py | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index fd5062036..252537b04 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -1,14 +1,14 @@ pre { - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; } .wy-table-responsive table td, .wy-table-responsive table th { - white-space: normal; + white-space: normal; } .rst-content table.docutils td { - vertical-align: top; + vertical-align: top; } diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html index 5f81b2320..41713a109 100644 --- a/docs/_templates/layout.html +++ b/docs/_templates/layout.html @@ -1,6 +1,6 @@ {% extends "!layout.html" %} - {% block menu %} +{% block menu %} {{ super() }} - Keyword Index - {% endblock %} + Keyword Index +{% endblock %} diff --git a/docs/conf.py b/docs/conf.py index 60d50fe51..6cf5b8b75 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -238,7 +238,7 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'solidity.tex', 'Solidity Documentation', 'Ethereum', 'manual'), + ('index', 'solidity.tex', 'Solidity Documentation', 'Ethereum', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of From 551c3ae17a7e8d931a933031fffa8bad1fb8194b Mon Sep 17 00:00:00 2001 From: 4molybdenum2 Date: Fri, 10 Sep 2021 15:46:43 +0530 Subject: [PATCH 11/62] Adjust Colors for the Solidity Docs --- docs/_static/css/custom.css | 34 ++++++++++++++++++++++++++++++++++ docs/_static/css/dark.css | 17 ++++++++++++----- docs/conf.py | 8 ++++++-- docs/index.rst | 7 +------ 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 252537b04..7fbda74b7 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -12,3 +12,37 @@ pre { .rst-content table.docutils td { vertical-align: top; } + +/* links */ +.rst-content a:not(:visited) { + color: #002fa7; +} + +.rst-content .highlighted { + background: #eac545; +} + +/* code block highlights */ +.rst-content pre { + background: #fafafa; +} + +.wy-side-nav-search img.logo { + width: 100px !important; + padding: 0; +} + +.wy-side-nav-search > a { + padding: 0; + margin: 0; +} + +/* project version (displayed under project logo) */ +.wy-side-nav-search .version { + color: #272525 !important; +} + +/* menu section headers */ +.wy-menu .caption { + color: #65afff !important; +} diff --git a/docs/_static/css/dark.css b/docs/_static/css/dark.css index f9b445898..f93f1aa2d 100644 --- a/docs/_static/css/dark.css +++ b/docs/_static/css/dark.css @@ -1,11 +1,9 @@ /* links */ -a, -a:visited { - color: #aaddff; +.rst-content a:not(:visited) { + color: #aaddff !important; } - /* code directives */ .method dt, @@ -46,6 +44,9 @@ em.property { background-color: #5a5a5a; } +.rst-content pre { + background: none; +} /* inlined code highlights */ @@ -70,6 +71,12 @@ code.docutils.literal.notranslate { color: #ddd; } +/* highlight color search text */ + +.rst-content .highlighted { + background: #ff5722; + box-shadow: 0 0 0 2px #f0978b; +} /* notes, warnings, hints */ @@ -619,4 +626,4 @@ code.docutils.literal.notranslate { } -/* Literal.Number.Integer.Long */ \ No newline at end of file +/* Literal.Number.Integer.Long */ diff --git a/docs/conf.py b/docs/conf.py index 6cf5b8b75..a46bac343 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -128,7 +128,11 @@ html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +html_theme_options = { + 'logo_only': True, + 'style_nav_header_background': '#65afff', + 'display_version': True, +} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] @@ -142,7 +146,7 @@ html_theme = 'sphinx_rtd_theme' # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +html_logo = "logo.svg" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 diff --git a/docs/index.rst b/docs/index.rst index 024a872f1..d702a28c9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,11 +1,6 @@ Solidity ======== -.. image:: logo.svg - :width: 120px - :alt: Solidity logo - :align: center - Solidity is an object-oriented, high-level language for implementing smart contracts. Smart contracts are programs which govern the behaviour of accounts within the Ethereum state. @@ -172,4 +167,4 @@ Contents bugs.rst contributing.rst brand-guide.rst - language-influences.rst \ No newline at end of file + language-influences.rst From e13dc5084d9556d22c8c63fdb4aead1d31a03c70 Mon Sep 17 00:00:00 2001 From: Saurabh Sharma Date: Mon, 9 Aug 2021 15:06:29 +0530 Subject: [PATCH 12/62] Move exception handlers from CommandLineInterface to main() --- solc/CommandLineInterface.cpp | 119 +++------------------------------- solc/main.cpp | 61 +++++++++++++---- 2 files changed, 55 insertions(+), 125 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index dfe5cfc5c..a825dd2a4 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -699,30 +699,6 @@ bool CommandLineInterface::compile() formatter.printExceptionInformation(_exception, "Compiler error"); return false; } - catch (InternalCompilerError const& _exception) - { - serr() << - "Internal compiler error during compilation:" << - endl << - boost::diagnostic_information(_exception); - return false; - } - catch (UnimplementedFeatureError const& _exception) - { - serr() << - "Unimplemented feature:" << - endl << - boost::diagnostic_information(_exception); - return false; - } - catch (smtutil::SMTLogicError const& _exception) - { - serr() << - "SMT logic error during analysis:" << - endl << - boost::diagnostic_information(_exception); - return false; - } catch (Error const& _error) { if (_error.type() == Error::Type::DocstringParsingError) @@ -735,23 +711,6 @@ bool CommandLineInterface::compile() return false; } - catch (Exception const& _exception) - { - serr() << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; - return false; - } - catch (std::exception const& _e) - { - serr() << "Unknown exception during compilation" << ( - _e.what() ? ": " + string(_e.what()) : "." - ) << endl; - return false; - } - catch (...) - { - serr() << "Unknown exception during compilation." << endl; - return false; - } return true; } @@ -1016,31 +975,10 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul: m_options.optimiserSettings() ); - try - { - if (!stack.parseAndAnalyze(src.first, src.second)) - successful = false; - else - stack.optimize(); - } - catch (Exception const& _exception) - { - serr() << "Exception in assembler: " << boost::diagnostic_information(_exception) << endl; - return false; - } - catch (std::exception const& _e) - { - serr() << - "Unknown exception during compilation" << - (_e.what() ? ": " + string(_e.what()) : ".") << - endl; - return false; - } - catch (...) - { - serr() << "Unknown exception in assembler." << endl; - return false; - } + if (!stack.parseAndAnalyze(src.first, src.second)) + successful = false; + else + stack.optimize(); } for (auto const& sourceAndStack: assemblyStacks) @@ -1074,29 +1012,8 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul: if (_language != yul::AssemblyStack::Language::Ewasm && _targetMachine == yul::AssemblyStack::Machine::Ewasm) { - try - { - stack.translate(yul::AssemblyStack::Language::Ewasm); - stack.optimize(); - } - catch (Exception const& _exception) - { - serr() << "Exception in assembler: " << boost::diagnostic_information(_exception) << endl; - return false; - } - catch (std::exception const& _e) - { - serr() << - "Unknown exception during compilation" << - (_e.what() ? ": " + string(_e.what()) : ".") << - endl; - return false; - } - catch (...) - { - serr() << "Unknown exception in assembler." << endl; - return false; - } + stack.translate(yul::AssemblyStack::Language::Ewasm); + stack.optimize(); sout() << endl << "==========================" << endl; sout() << endl << "Translated source:" << endl; @@ -1104,28 +1021,8 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul: } yul::MachineAssemblyObject object; - try - { - object = stack.assemble(_targetMachine); - object.bytecode->link(m_options.linker.libraries); - } - catch (Exception const& _exception) - { - serr() << "Exception while assembling: " << boost::diagnostic_information(_exception) << endl; - return false; - } - catch (std::exception const& _e) - { - serr() << "Unknown exception during compilation" << ( - _e.what() ? ": " + string(_e.what()) : "." - ) << endl; - return false; - } - catch (...) - { - serr() << "Unknown exception while assembling." << endl; - return false; - } + object = stack.assemble(_targetMachine); + object.bytecode->link(m_options.linker.libraries); sout() << endl << "Binary representation:" << endl; if (object.bytecode) diff --git a/solc/main.cpp b/solc/main.cpp index 9eefc1afd..1299e2564 100644 --- a/solc/main.cpp +++ b/solc/main.cpp @@ -22,11 +22,16 @@ */ #include + +#include + #include + #include #include using namespace std; +using namespace solidity; /* The equivalent of setlocale(LC_ALL, "C") is called before any user code is run. @@ -53,24 +58,52 @@ static void setDefaultOrCLocale() int main(int argc, char** argv) { - setDefaultOrCLocale(); - solidity::frontend::CommandLineInterface cli(cin, cout, cerr); - if (!cli.parseArguments(argc, argv)) - return 1; - if (!cli.readInputFiles()) - return 1; - if (!cli.processInput()) - return 1; - bool success = false; try { - success = cli.actOnInput(); + setDefaultOrCLocale(); + solidity::frontend::CommandLineInterface cli(cin, cout, cerr); + bool success = + cli.parseArguments(argc, argv) && + cli.readInputFiles() && + cli.processInput() && + cli.actOnInput(); + + return success ? 0 : 1; + } + catch (smtutil::SMTLogicError const& _exception) + { + cerr << "SMT logic error:" << endl; + cerr << boost::diagnostic_information(_exception); + return 1; + } + catch (langutil::UnimplementedFeatureError const& _exception) + { + cerr << "Unimplemented feature:" << endl; + cerr << boost::diagnostic_information(_exception); + return 1; + } + catch (langutil::InternalCompilerError const& _exception) + { + cerr << "Internal compiler error:" << endl; + cerr << boost::diagnostic_information(_exception); + return 1; } catch (boost::exception const& _exception) { - cerr << "Exception during output generation: " << boost::diagnostic_information(_exception) << endl; - success = false; + cerr << "Uncaught exception:" << endl; + cerr << boost::diagnostic_information(_exception) << endl; + return 1; + } + catch (std::exception const& _exception) + { + cerr << "Uncaught exception:" << endl; + cerr << boost::diagnostic_information(_exception) << endl; + return 1; + } + catch (...) + { + cerr << "Uncaught exception" << endl; + cerr << boost::current_exception_diagnostic_information() << endl; + return 1; } - - return success ? 0 : 1; } From a30348715b2fe69cecfdcbfbe49ebebd91d2db9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 7 Oct 2021 17:40:57 +0200 Subject: [PATCH 13/62] Use boost::current_exception_diagnostic_information() to print extra info about exceptions caught by (...) --- libsolidity/interface/FileReader.cpp | 2 +- libsolidity/interface/StandardCompiler.cpp | 8 ++++---- test/boostTest.cpp | 4 ++++ test/libsolidity/SolidityExpressionCompiler.cpp | 9 +++++++-- test/tools/isoltest.cpp | 6 ++---- tools/solidityUpgrade/SourceUpgrade.cpp | 8 ++++---- tools/solidityUpgrade/main.cpp | 4 ++++ 7 files changed, 26 insertions(+), 15 deletions(-) diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index 2a1859d21..6bf5db75c 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -171,7 +171,7 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so } catch (...) { - return ReadCallback::Result{false, "Unknown exception in read callback."}; + return ReadCallback::Result{false, "Unknown exception in read callback: " + boost::current_exception_diagnostic_information()}; } } diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 7d354a405..446253f0a 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1151,13 +1151,13 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting "Exception during compilation: " + boost::diagnostic_information(_exception) )); } - catch (std::exception const& _e) + catch (std::exception const& _exception) { errors.append(formatError( Error::Severity::Error, "Exception", "general", - "Unknown exception during compilation" + (_e.what() ? ": " + string(_e.what()) : ".") + "Unknown exception during compilation: " + boost::diagnostic_information(_exception) )); } catch (...) @@ -1166,7 +1166,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting Error::Severity::Error, "Exception", "general", - "Unknown exception during compilation." + "Unknown exception during compilation: " + boost::current_exception_diagnostic_information() )); } @@ -1481,7 +1481,7 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept } catch (...) { - return formatFatalError("InternalCompilerError", "Internal exception in StandardCompiler::compile"); + return formatFatalError("InternalCompilerError", "Internal exception in StandardCompiler::compile: " + boost::current_exception_diagnostic_information()); } } diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 537ab516e..6fcd684f4 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -87,6 +87,10 @@ void runTestCase(TestCase::Config const& _config, TestCase::TestCaseCreator cons { BOOST_ERROR("Exception during extracted test: " << boost::diagnostic_information(_e)); } + catch (...) + { + BOOST_ERROR("Unknown exception during extracted test: " << boost::current_exception_diagnostic_information()); + } } int registerTests( diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index ee1bf0239..5f7b8d472 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -112,9 +112,14 @@ bytes compileFirstExpression( if (!sourceUnit) return bytes(); } - catch(boost::exception const& _e) + catch (boost::exception const& _e) { - auto msg = std::string("Parsing source code failed with: \n") + boost::diagnostic_information(_e); + string msg = "Parsing source code failed with:\n" + boost::diagnostic_information(_e); + BOOST_FAIL(msg); + } + catch (...) + { + string msg = "Parsing source code failed with:\n" + boost::current_exception_diagnostic_information(); BOOST_FAIL(msg); } diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 73adbc62b..5ae1a3f99 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -201,15 +201,13 @@ TestTool::Result TestTool::process() catch (std::exception const& _e) { AnsiColorized(cout, formatted, {BOLD, RED}) << - "Exception during test" << - (_e.what() ? ": " + string(_e.what()) : ".") << - endl; + "Exception during test: " << boost::diagnostic_information(_e) << endl; return Result::Exception; } catch (...) { AnsiColorized(cout, formatted, {BOLD, RED}) << - "Unknown exception during test." << endl; + "Unknown exception during test: " << boost::current_exception_diagnostic_information() << endl; return Result::Exception; } } diff --git a/tools/solidityUpgrade/SourceUpgrade.cpp b/tools/solidityUpgrade/SourceUpgrade.cpp index 85dca2297..c102be387 100644 --- a/tools/solidityUpgrade/SourceUpgrade.cpp +++ b/tools/solidityUpgrade/SourceUpgrade.cpp @@ -306,13 +306,13 @@ void SourceUpgrade::tryCompile() const { error() << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; } - catch (std::exception const& _e) + catch (std::exception const& _exception) { - error() << (_e.what() ? ": " + string(_e.what()) : ".") << endl; + error() << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; } catch (...) { - error() << "Unknown exception during compilation." << endl; + error() << "Unknown exception during compilation: " << boost::current_exception_diagnostic_information() << endl; } } @@ -517,7 +517,7 @@ ReadCallback::Callback SourceUpgrade::fileReader() } catch (...) { - return ReadCallback::Result{false, "Unknown exception in read callback."}; + return ReadCallback::Result{false, "Unknown exception in read callback: " + boost::current_exception_diagnostic_information()}; } }; diff --git a/tools/solidityUpgrade/main.cpp b/tools/solidityUpgrade/main.cpp index 11026884a..55ed0118c 100644 --- a/tools/solidityUpgrade/main.cpp +++ b/tools/solidityUpgrade/main.cpp @@ -86,6 +86,10 @@ int main(int argc, char** argv) { cerr << "Exception while processing input: " << boost::diagnostic_information(_exception) << endl; } + catch (...) + { + cerr << "Unknown exception while processing input: " << boost::current_exception_diagnostic_information() << endl; + } return 0; } From cd7db7faebdffc66ed3730662094b0927eaf84e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 20 Sep 2021 12:22:05 +0200 Subject: [PATCH 14/62] Add an arrow icon for Remix link, with proper attribution --- docs/_static/img/share-solid.svg | 1 + docs/_templates/footer.html | 6 ++++++ docs/credits-and-attribution.rst | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 docs/_static/img/share-solid.svg create mode 100644 docs/_templates/footer.html create mode 100644 docs/credits-and-attribution.rst diff --git a/docs/_static/img/share-solid.svg b/docs/_static/img/share-solid.svg new file mode 100644 index 000000000..1a1e61004 --- /dev/null +++ b/docs/_static/img/share-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/_templates/footer.html b/docs/_templates/footer.html new file mode 100644 index 000000000..28a09e8b9 --- /dev/null +++ b/docs/_templates/footer.html @@ -0,0 +1,6 @@ +{% extends "!footer.html" %} + +{% block extrafooter %} +
+ Credits and attribution. +{% endblock %} diff --git a/docs/credits-and-attribution.rst b/docs/credits-and-attribution.rst new file mode 100644 index 000000000..1a8067c8e --- /dev/null +++ b/docs/credits-and-attribution.rst @@ -0,0 +1,21 @@ +.. This page is meant to be linked to from the footer. + +:orphan: + +####################### +Credits and Attribution +####################### + +Website icons +============= + +.. |icon-share-solid| image:: _static/img/share-solid.svg +.. _share icon: https://fontawesome.com/v5.15/icons/share?style=solid +.. _Font Awesome Free License: https://fontawesome.com/license/free + ++-------------------------+-----------------------------------------------------------------------+ +| Icon | Attribution | ++=========================+=======================================================================+ +| |icon-share-solid| | - Source: `share icon`_ from Font Awesome 5.15.0. | +| | - License: `Font Awesome Free License`_ (CC BY 4.0). | ++-------------------------+-----------------------------------------------------------------------+ From 416b13850fb4ac89513242971cbf184cdf798696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 26 Jul 2021 19:52:05 +0200 Subject: [PATCH 15/62] Sphinx extension for adding Remix links to code snippets --- docs/_static/css/custom.css | 36 ++++++++++++++++ docs/_static/css/dark.css | 6 +++ docs/conf.py | 1 + docs/ext/remix_code_links.py | 80 ++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 docs/ext/remix_code_links.py diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 7fbda74b7..02dea07c8 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -45,4 +45,40 @@ pre { /* menu section headers */ .wy-menu .caption { color: #65afff !important; + +/* Link to Remix IDE shown next to code snippets */ +p.remix-link-container { + position: relative; + right: -100%; /* Positioned next to the the top-right corner of the code block following it. */ } + +a.remix-link { + position: absolute; /* Remove it from normal flow not to affect the original position of the snippet. */ + top: 0.5em; + width: 3.236em; /* Size of the margin (= right-side padding in .wy-nav-content in the current theme). */ +} + +a.remix-link .link-icon { + background: url("../img/share-solid.svg") no-repeat; + display: block; + width: 1.5em; + height: 1.5em; + margin: auto; +} + +a.remix-link .link-text { + display: none; /* Visible only on hover. */ + width: 3.3em; /* Narrow enough to get two lines of text. */ + margin: auto; + text-align: center; + font-size: 0.8em; + line-height: normal; + color: black; +} + +a.remix-link:hover { + opacity: 0.5; +} + +a.remix-link:hover .link-text { + display: block; diff --git a/docs/_static/css/dark.css b/docs/_static/css/dark.css index f93f1aa2d..a87ff09eb 100644 --- a/docs/_static/css/dark.css +++ b/docs/_static/css/dark.css @@ -627,3 +627,9 @@ code.docutils.literal.notranslate { /* Literal.Number.Integer.Long */ + + +/* Link to Remix IDE shown over code snippets */ +a.remix-link { + filter: invert(1); /* The icon is black. In dark mode we want it white. */ +} diff --git a/docs/conf.py b/docs/conf.py index a46bac343..b75eb966d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -44,6 +44,7 @@ def setup(sphinx): extensions = [ 'sphinx_a4doc', 'html_extra_template_renderer', + 'remix_code_links', ] a4_base_path = os.path.dirname(__file__) + '/grammar' diff --git a/docs/ext/remix_code_links.py b/docs/ext/remix_code_links.py new file mode 100644 index 000000000..7e7e558ea --- /dev/null +++ b/docs/ext/remix_code_links.py @@ -0,0 +1,80 @@ +import base64 +import docutils # pragma pylint: disable=import-error + +from sphinx.util import logging # pragma pylint: disable=import-error + +# NOTE: 2000 should generally be safe for all browsers, while 8000 for most of them. +MAX_SAFE_URL_LENGTH = 10000 + +logger = logging.getLogger(__name__) + + +def insert_node_before(child, new_sibling): + assert child in child.parent.children + + for position, node in enumerate(child.parent.children): + if node == child: + child.parent.insert(position, new_sibling) + break + + +def remix_code_url(source_code): + # NOTE: base64 encoded data may contain +, = and / characters. Remix seems to handle them just + # fine without any escaping. + base64_encoded_source = base64.b64encode(source_code.encode('utf-8')).decode('ascii') + return f"https://remix.ethereum.org/?code={base64_encoded_source}" + + +def build_remix_link_node(url): + link_icon_node = docutils.nodes.inline() + link_icon_node.set_class('link-icon') + + link_text_node = docutils.nodes.inline(text="open in Remix") + link_text_node.set_class('link-text') + + reference_node = docutils.nodes.reference('', '', internal=False, refuri=url) + reference_node.set_class('remix-link') + reference_node += [link_icon_node, link_text_node] + + paragraph_node = docutils.nodes.paragraph() + paragraph_node.set_class('remix-link-container') + paragraph_node += reference_node + return paragraph_node + + +def insert_remix_link(app, doctree): + if app.builder.format != 'html' or app.builder.name == 'epub': + return + + for literal_block_node in doctree.traverse(docutils.nodes.literal_block): + assert 'language' in literal_block_node.attributes + if literal_block_node.attributes['language'].lower() == 'solidity': + text_nodes = list(literal_block_node.traverse(docutils.nodes.Text)) + assert len(text_nodes) == 1 + + remix_url = remix_code_url(text_nodes[0]) + url_length = len(remix_url.encode('utf-8')) + if url_length > MAX_SAFE_URL_LENGTH: + logger.warning( + "Remix URL generated from the code snippet exceeds the maximum safe URL length " + " (%d > %d bytes).", + url_length, + MAX_SAFE_URL_LENGTH, + location=(literal_block_node.source, literal_block_node.line), + ) + + insert_node_before(literal_block_node, build_remix_link_node(remix_url)) + + +def setup(app): + app.connect( + 'doctree-resolved', + lambda app, doctree, docname: insert_remix_link(app, doctree) + ) + + return { + # NOTE: Need to access _raw_config here because setup() runs before app.config is ready. + 'version': app.config._raw_config['version'], # pylint: disable=protected-access + 'parallel_read_safe': True, + 'parallel_write_safe': True, + } From b7942219dfc479d01825ec22cccbb4540d7a0d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 20 Sep 2021 12:11:23 +0200 Subject: [PATCH 16/62] Include language and compiler version in Remix code links --- docs/ext/remix_code_links.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/ext/remix_code_links.py b/docs/ext/remix_code_links.py index 7e7e558ea..2fc15ddda 100644 --- a/docs/ext/remix_code_links.py +++ b/docs/ext/remix_code_links.py @@ -18,11 +18,11 @@ def insert_node_before(child, new_sibling): break -def remix_code_url(source_code): +def remix_code_url(source_code, language, solidity_version): # NOTE: base64 encoded data may contain +, = and / characters. Remix seems to handle them just # fine without any escaping. base64_encoded_source = base64.b64encode(source_code.encode('utf-8')).decode('ascii') - return f"https://remix.ethereum.org/?code={base64_encoded_source}" + return f"https://remix.ethereum.org/?language={language}&version={solidity_version}&code={base64_encoded_source}" def build_remix_link_node(url): @@ -42,17 +42,18 @@ def build_remix_link_node(url): return paragraph_node -def insert_remix_link(app, doctree): +def insert_remix_link(app, doctree, solidity_version): if app.builder.format != 'html' or app.builder.name == 'epub': return for literal_block_node in doctree.traverse(docutils.nodes.literal_block): assert 'language' in literal_block_node.attributes - if literal_block_node.attributes['language'].lower() == 'solidity': + language = literal_block_node.attributes['language'].lower() + if language in ['solidity', 'yul']: text_nodes = list(literal_block_node.traverse(docutils.nodes.Text)) assert len(text_nodes) == 1 - remix_url = remix_code_url(text_nodes[0]) + remix_url = remix_code_url(text_nodes[0], language, solidity_version) url_length = len(remix_url.encode('utf-8')) if url_length > MAX_SAFE_URL_LENGTH: logger.warning( @@ -67,14 +68,16 @@ def insert_remix_link(app, doctree): def setup(app): + # NOTE: Need to access _raw_config here because setup() runs before app.config is ready. + solidity_version = app.config._raw_config['version'] # pylint: disable=protected-access + app.connect( 'doctree-resolved', - lambda app, doctree, docname: insert_remix_link(app, doctree) + lambda app, doctree, docname: insert_remix_link(app, doctree, solidity_version) ) return { - # NOTE: Need to access _raw_config here because setup() runs before app.config is ready. - 'version': app.config._raw_config['version'], # pylint: disable=protected-access + 'version': solidity_version, 'parallel_read_safe': True, 'parallel_write_safe': True, } From 6adfe88211ecbd3f3cbc7128a3f13bedd2e269d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 7 Oct 2021 21:20:51 +0200 Subject: [PATCH 17/62] custom.css: Restore braces that disappeared in a rebase --- docs/_static/css/custom.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 02dea07c8..f738ecb6a 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -45,6 +45,7 @@ pre { /* menu section headers */ .wy-menu .caption { color: #65afff !important; +} /* Link to Remix IDE shown next to code snippets */ p.remix-link-container { @@ -82,3 +83,4 @@ a.remix-link:hover { a.remix-link:hover .link-text { display: block; +} From f245f8b473d6a79374a03f7fe748c04e9e1fde68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 7 Oct 2021 21:22:12 +0200 Subject: [PATCH 18/62] footer.html: Put credits link in a paragraph to add more spacing --- docs/_templates/footer.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/_templates/footer.html b/docs/_templates/footer.html index 28a09e8b9..59c7d7581 100644 --- a/docs/_templates/footer.html +++ b/docs/_templates/footer.html @@ -1,6 +1,7 @@ {% extends "!footer.html" %} {% block extrafooter %} -
- Credits and attribution. +

+ Credits and attribution. +

{% endblock %} From d22cd235cf55fe84264443a1abb4b1799b592182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 8 Oct 2021 13:09:48 +0200 Subject: [PATCH 19/62] Rename share-solid.svg to avoid it being blocked by adblockers --- docs/_static/css/custom.css | 2 +- docs/_static/img/{share-solid.svg => solid-share-arrow.svg} | 0 docs/credits-and-attribution.rst | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename docs/_static/img/{share-solid.svg => solid-share-arrow.svg} (100%) diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index f738ecb6a..4ff53f3a7 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -60,7 +60,7 @@ a.remix-link { } a.remix-link .link-icon { - background: url("../img/share-solid.svg") no-repeat; + background: url("../img/solid-share-arrow.svg") no-repeat; display: block; width: 1.5em; height: 1.5em; diff --git a/docs/_static/img/share-solid.svg b/docs/_static/img/solid-share-arrow.svg similarity index 100% rename from docs/_static/img/share-solid.svg rename to docs/_static/img/solid-share-arrow.svg diff --git a/docs/credits-and-attribution.rst b/docs/credits-and-attribution.rst index 1a8067c8e..f1aa6cfd3 100644 --- a/docs/credits-and-attribution.rst +++ b/docs/credits-and-attribution.rst @@ -9,7 +9,7 @@ Credits and Attribution Website icons ============= -.. |icon-share-solid| image:: _static/img/share-solid.svg +.. |icon-share-solid| image:: _static/img/solid-share-arrow.svg .. _share icon: https://fontawesome.com/v5.15/icons/share?style=solid .. _Font Awesome Free License: https://fontawesome.com/license/free From 3f08b2269aae767df5dbf13d40f6900e3585fdd3 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Tue, 20 Apr 2021 14:12:07 +0200 Subject: [PATCH 20/62] Adds fmtlib as 3rdparty dependency for easier string composition. --- CMakeLists.txt | 1 + cmake/fmtlib.cmake | 20 ++++++++++++++++ libevmasm/CMakeLists.txt | 2 +- liblangutil/CMakeLists.txt | 2 +- libsolidity/CMakeLists.txt | 2 +- libyul/AsmAnalysis.cpp | 24 ++++++++----------- libyul/CMakeLists.txt | 2 +- libyul/YulString.h | 22 +++++++++++++++++ scripts/release_ppa.sh | 3 ++- test/libyul/yulSyntaxTests/invalid_type4.yul | 2 +- .../yulSyntaxTests/type_check_cases_fail.yul | 4 ++-- .../type_check_cases_fail_evmtyped.yul | 4 ++-- 12 files changed, 64 insertions(+), 24 deletions(-) create mode 100644 cmake/fmtlib.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 6014cc6fa..23c2f0e42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ include(EthCcache) # Let's find our dependencies include(EthDependencies) +include(fmtlib) include(jsoncpp) include(range-v3) include_directories(SYSTEM ${JSONCPP_INCLUDE_DIR}) diff --git a/cmake/fmtlib.cmake b/cmake/fmtlib.cmake new file mode 100644 index 000000000..5ed196cea --- /dev/null +++ b/cmake/fmtlib.cmake @@ -0,0 +1,20 @@ +include(FetchContent) + +FetchContent_Declare( + fmtlib + PREFIX "${CMAKE_BINARY_DIR}/deps" + DOWNLOAD_DIR "${CMAKE_SOURCE_DIR}/deps/downloads" + DOWNLOAD_NAME fmt-8.0.1.tar.gz + URL https://github.com/fmtlib/fmt/archive/8.0.1.tar.gz + URL_HASH SHA256=b06ca3130158c625848f3fb7418f235155a4d389b2abc3a6245fb01cb0eb1e01 +) + +if (CMAKE_VERSION VERSION_LESS "3.14.0") + FetchContent_GetProperties(fmtlib) + if (NOT fmtlib_POPULATED) + FetchContent_Populate(fmtlib) + add_subdirectory(${fmtlib_SOURCE_DIR} ${fmtlib_BINARY_DIR}) + endif() +else() + FetchContent_MakeAvailable(fmtlib) +endif() diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index 5b3afcdb6..4e392aadd 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -38,4 +38,4 @@ set(sources ) add_library(evmasm ${sources}) -target_link_libraries(evmasm PUBLIC solutil) +target_link_libraries(evmasm PUBLIC solutil fmt::fmt-header-only) diff --git a/liblangutil/CMakeLists.txt b/liblangutil/CMakeLists.txt index 96f2a23d8..28216207c 100644 --- a/liblangutil/CMakeLists.txt +++ b/liblangutil/CMakeLists.txt @@ -29,4 +29,4 @@ set(sources ) add_library(langutil ${sources}) -target_link_libraries(langutil PUBLIC solutil) +target_link_libraries(langutil PUBLIC solutil fmt::fmt-header-only) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 24b7d2d85..a1cb68c35 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -159,4 +159,4 @@ set(sources ) add_library(solidity ${sources}) -target_link_libraries(solidity PUBLIC yul evmasm langutil smtutil solutil Boost::boost) +target_link_libraries(solidity PUBLIC yul evmasm langutil smtutil solutil Boost::boost fmt::fmt-header-only) diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index aae1c97e1..d19aa1a4e 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -37,6 +37,8 @@ #include +#include + #include #include @@ -643,7 +645,7 @@ void AsmAnalyzer::expectValidType(YulString _type, SourceLocation const& _locati m_errorReporter.typeError( 5473_error, _location, - "\"" + _type.str() + "\" is not a valid type (user defined types are not yet supported)." + fmt::format("\"{}\" is not a valid type (user defined types are not yet supported).", _type) ); } @@ -653,11 +655,7 @@ void AsmAnalyzer::expectType(YulString _expectedType, YulString _givenType, Sour m_errorReporter.typeError( 3781_error, _location, - "Expected a value of type \"" + - _expectedType.str() + - "\" but got \"" + - _givenType.str() + - "\"" + fmt::format("Expected a value of type \"{}\" but got \"{}\".", _expectedType, _givenType) ); } @@ -689,14 +687,12 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio m_errorReporter.typeError( _errorId, _location, - "The \"" + - boost::to_lower_copy(instructionInfo(_instr).name) - + "\" instruction is " + - vmKindMessage + - " VMs " + - "(you are currently compiling for \"" + - m_evmVersion.name() + - "\")." + fmt::format( + "The \"{instruction}\" instruction is {kind} VMs (you are currently compiling for \"{version}\").", + fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr).name)), + fmt::arg("kind", vmKindMessage), + fmt::arg("version", m_evmVersion.name()) + ) ); }; diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 2cc5578e8..0ddb9c64a 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -216,4 +216,4 @@ add_library(yul optimiser/VarNameCleaner.h ) -target_link_libraries(yul PUBLIC evmasm solutil langutil smtutil) +target_link_libraries(yul PUBLIC evmasm solutil langutil smtutil fmt::fmt-header-only) diff --git a/libyul/YulString.h b/libyul/YulString.h index fc3dedfd4..5522e3484 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -21,6 +21,8 @@ #pragma once +#include + #include #include #include @@ -166,6 +168,26 @@ inline YulString operator "" _yulstring(char const* _string, std::size_t _size) } } + +namespace fmt +{ +template <> +struct formatter +{ + template + constexpr auto parse(ParseContext& _context) + { + return _context.begin(); + } + + template + auto format(solidity::yul::YulString _value, FormatContext& _context) + { + return format_to(_context.out(), "{}", _value.str()); + } +}; +} + namespace std { template<> struct hash diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index a798b96a5..a06a779d6 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -105,10 +105,11 @@ ppafilesurl=https://launchpad.net/~ethereum/+archive/ubuntu/${pparepo}/+files git clone --depth 2 --recursive https://github.com/ethereum/solidity.git -b "$branch" mv solidity solc -# Fetch jsoncpp dependency +# Fetch dependencies mkdir -p ./solc/deps/downloads/ 2>/dev/null || true wget -O ./solc/deps/downloads/jsoncpp-1.9.3.tar.gz https://github.com/open-source-parsers/jsoncpp/archive/1.9.3.tar.gz wget -O ./solc/deps/downloads/range-v3-0.11.0.tar.gz https://github.com/ericniebler/range-v3/archive/0.11.0.tar.gz +wget -O ./solc/deps/downloads/fmt-7.1.3.tar.gz https://github.com/fmtlib/fmt/archive/7.1.3.tar.gz # Determine version cd solc diff --git a/test/libyul/yulSyntaxTests/invalid_type4.yul b/test/libyul/yulSyntaxTests/invalid_type4.yul index 0c588a831..8195fcf90 100644 --- a/test/libyul/yulSyntaxTests/invalid_type4.yul +++ b/test/libyul/yulSyntaxTests/invalid_type4.yul @@ -5,5 +5,5 @@ // ==== // dialect: evmTyped // ---- -// TypeError 3781: (24-38): Expected a value of type "u256" but got "invalidType" +// TypeError 3781: (24-38): Expected a value of type "u256" but got "invalidType". // TypeError 5473: (24-38): "invalidType" is not a valid type (user defined types are not yet supported). diff --git a/test/libyul/yulSyntaxTests/type_check_cases_fail.yul b/test/libyul/yulSyntaxTests/type_check_cases_fail.yul index 1b3f779d1..d9b4c0204 100644 --- a/test/libyul/yulSyntaxTests/type_check_cases_fail.yul +++ b/test/libyul/yulSyntaxTests/type_check_cases_fail.yul @@ -6,5 +6,5 @@ // ==== // dialect: ewasm // ---- -// TypeError 3781: (28-33): Expected a value of type "i32" but got "i64" -// TypeError 3781: (46-51): Expected a value of type "i32" but got "i64" +// TypeError 3781: (28-33): Expected a value of type "i32" but got "i64". +// TypeError 3781: (46-51): Expected a value of type "i32" but got "i64". diff --git a/test/libyul/yulSyntaxTests/type_check_cases_fail_evmtyped.yul b/test/libyul/yulSyntaxTests/type_check_cases_fail_evmtyped.yul index 458372fe9..35926ccb2 100644 --- a/test/libyul/yulSyntaxTests/type_check_cases_fail_evmtyped.yul +++ b/test/libyul/yulSyntaxTests/type_check_cases_fail_evmtyped.yul @@ -6,5 +6,5 @@ // ==== // dialect: evmTyped // ---- -// TypeError 3781: (24-33): Expected a value of type "u256" but got "bool" -// TypeError 3781: (46-55): Expected a value of type "u256" but got "bool" +// TypeError 3781: (24-33): Expected a value of type "u256" but got "bool". +// TypeError 3781: (46-55): Expected a value of type "u256" but got "bool". From b986c2151abcbec956584906a82feb654cedd34c Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 11 Oct 2021 13:18:43 +0200 Subject: [PATCH 21/62] Add inline assembly section to cleanup. --- docs/internals/variable_cleanup.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/internals/variable_cleanup.rst b/docs/internals/variable_cleanup.rst index 1718fc66b..9fec6929f 100644 --- a/docs/internals/variable_cleanup.rst +++ b/docs/internals/variable_cleanup.rst @@ -14,7 +14,12 @@ hashes or sent as the data of a message call. Similarly, before storing a value in the storage, the remaining bits need to be cleaned because otherwise the garbled value can be observed. -On the other hand, we do not clean the bits if the immediately +Note that access via inline assembly is not considered such an operation: +If you use inline assembly to access Solidity variables +shorter than 256 bits, the compiler does not guarantee that +the value is properly cleaned up. + +Moreover, we do not clean the bits if the immediately following operation is not affected. For instance, since any non-zero value is considered ``true`` by ``JUMPI`` instruction, we do not clean the boolean values before they are used as the condition for From 859a17027316c957e9013c3b0923031c406f9801 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Mon, 11 Oct 2021 14:52:07 +0200 Subject: [PATCH 22/62] Updates PPA release script to pre-fetch the correct fmtlib version. --- scripts/release_ppa.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index a06a779d6..60e931083 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -109,7 +109,7 @@ mv solidity solc mkdir -p ./solc/deps/downloads/ 2>/dev/null || true wget -O ./solc/deps/downloads/jsoncpp-1.9.3.tar.gz https://github.com/open-source-parsers/jsoncpp/archive/1.9.3.tar.gz wget -O ./solc/deps/downloads/range-v3-0.11.0.tar.gz https://github.com/ericniebler/range-v3/archive/0.11.0.tar.gz -wget -O ./solc/deps/downloads/fmt-7.1.3.tar.gz https://github.com/fmtlib/fmt/archive/7.1.3.tar.gz +wget -O ./solc/deps/downloads/fmt-8.0.1.tar.gz https://github.com/fmtlib/fmt/archive/8.0.1.tar.gz # Determine version cd solc From 24c8a608c491de8886f8c55c0955d116c42607eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 7 Oct 2021 18:09:18 +0200 Subject: [PATCH 23/62] Include OS and CPU architecture in CircleCI cache keys --- .circleci/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4706fe6c0..a859b8464 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -627,14 +627,14 @@ jobs: - checkout - restore_cache: keys: - - dependencies-osx-{{ checksum ".circleci/osx_install_dependencies.sh" }} + - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} # DO NOT EDIT between here and save_cache, but rather edit ./circleci/osx_install_dependencies.sh # WARNING! If you do edit anything here instead, remember to invalidate the cache manually. - run: name: Install build dependencies command: ./.circleci/osx_install_dependencies.sh - save_cache: - key: dependencies-osx-{{ checksum ".circleci/osx_install_dependencies.sh" }} + key: dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} paths: - /usr/local/bin - /usr/local/sbin @@ -663,7 +663,7 @@ jobs: - checkout - restore_cache: keys: - - dependencies-osx-{{ checksum ".circleci/osx_install_dependencies.sh" }} + - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} - attach_workspace: at: . - run: *run_soltest @@ -679,7 +679,7 @@ jobs: - checkout - restore_cache: keys: - - dependencies-osx-{{ checksum ".circleci/osx_install_dependencies.sh" }} + - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} - attach_workspace: at: . - run: *run_cmdline_tests @@ -886,14 +886,14 @@ jobs: - checkout - restore_cache: keys: - - dependencies-win-{{ checksum "scripts/install_deps.ps1" }} + - dependencies-win-{{ arch }}-{{ checksum "scripts/install_deps.ps1" }} # DO NOT EDIT between here and save_cache, but rather edit .\scripts\install_deps.ps1 # WARNING! If you do edit anything here instead, remember to invalidate the cache manually. - run: name: "Installing dependencies" command: .\scripts\install_deps.ps1 - save_cache: - key: dependencies-win-{{ checksum "scripts/install_deps.ps1" }} + key: dependencies-win-{{ arch }}-{{ checksum "scripts/install_deps.ps1" }} paths: - .\deps - run: From cd225740724954f724365caedc008f2cdd58cfb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 11 Oct 2021 19:58:05 +0200 Subject: [PATCH 24/62] Workaround for CircleCI not being able to restore cached /usr/local/Homebrew --- .circleci/config.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index a859b8464..5ed903ac5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -160,6 +160,17 @@ defaults: - store_test_results: *store_test_results - store_artifacts: *artifacts_test_results + - steps_restore_cache_homebrew_workaround: &steps_restore_cache_homebrew_workaround + steps: + - run: + # FIXME: For some reason restore_cache fails saying that it cannot remove the scm/ dir. + # The directory contains only two files: `git` (wrapper script over git) and `svn` (symlink + # to `git`). This looks like a bug in restore_cache. Removing scm/ is a workaround. + # See https://github.com/ethereum/solidity/pull/12106 for more details. + name: Workaround for restore_cache + /usr/local/Homebrew/Library/Homebrew/shims/scm/ + command: | + rm -r /usr/local/Homebrew/Library/Homebrew/shims/scm/ + - test_ubuntu1604_clang: &test_ubuntu1604_clang docker: - image: << pipeline.parameters.ubuntu-1604-clang-ossfuzz-docker-image >> @@ -625,6 +636,9 @@ jobs: MAKEFLAGS: -j 5 steps: - checkout + - when: + condition: true + <<: *steps_restore_cache_homebrew_workaround - restore_cache: keys: - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} @@ -661,6 +675,9 @@ jobs: TERM: xterm steps: - checkout + - when: + condition: true + <<: *steps_restore_cache_homebrew_workaround - restore_cache: keys: - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} @@ -677,6 +694,9 @@ jobs: TERM: xterm steps: - checkout + - when: + condition: true + <<: *steps_restore_cache_homebrew_workaround - restore_cache: keys: - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} From 2cd1c644b628ba6a58315dce1b81520344600095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 3 Sep 2021 19:39:10 +0200 Subject: [PATCH 25/62] Remove unused includes and sort existing includes in a few places --- libyul/backends/evm/ControlFlowGraphBuilder.cpp | 1 - test/libsolidity/InlineAssembly.cpp | 2 +- test/libsolidity/SolidityExecutionFramework.cpp | 11 +++++++---- test/libyul/Common.cpp | 5 ++--- test/libyul/Inliner.cpp | 1 - test/libyul/YulOptimizerTestCommon.cpp | 1 - test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp | 3 ++- test/tools/ossfuzz/yulProtoFuzzer.cpp | 2 +- tools/solidityUpgrade/SourceUpgrade.h | 1 - 9 files changed, 13 insertions(+), 14 deletions(-) diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index fd5b4682d..2c61bfb89 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 0ec9b50a2..7e539051d 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -28,8 +28,8 @@ #include -#include #include +#include #include #include diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 349baf481..95f0ba1ef 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -21,17 +21,20 @@ * Framework for executing Solidity contracts and testing them against C++ implementation. */ -#include -#include -#include #include + #include #include +#include + +#include +#include + using namespace solidity; -using namespace solidity::test; using namespace solidity::frontend; using namespace solidity::frontend::test; +using namespace solidity::test; using namespace std; bytes SolidityExecutionFramework::multiSourceCompileContract( diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 8099037f3..8e5dc55e6 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -23,8 +23,6 @@ #include -#include - #include #include #include @@ -33,8 +31,9 @@ #include #include -#include #include +#include +#include #include diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp index f80ec433e..75ae064e5 100644 --- a/test/libyul/Inliner.cpp +++ b/test/libyul/Inliner.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 00aba3c79..962cb18a4 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -61,7 +61,6 @@ #include #include #include -#include #include #include diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index e25de4f05..97bf0aebc 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -17,9 +17,10 @@ // SPDX-License-Identifier: GPL-3.0 #include -#include #include +#include + using namespace solidity; using namespace solidity::yul; using namespace std; diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index 7118a0596..f44ddaaa1 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -35,10 +35,10 @@ #include using namespace solidity; +using namespace solidity::langutil; using namespace solidity::yul; using namespace solidity::yul::test; using namespace solidity::yul::test::yul_fuzzer; -using namespace solidity::langutil; using namespace std; DEFINE_PROTO_FUZZER(Program const& _input) diff --git a/tools/solidityUpgrade/SourceUpgrade.h b/tools/solidityUpgrade/SourceUpgrade.h index 11e7e12a9..f3b5d3572 100644 --- a/tools/solidityUpgrade/SourceUpgrade.h +++ b/tools/solidityUpgrade/SourceUpgrade.h @@ -24,7 +24,6 @@ #include #include -#include #include #include From 25eedfafe22d7892e17cc97b4646b507eb39635d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 13 Sep 2021 12:10:51 +0200 Subject: [PATCH 26/62] Define DebugInfoSelection --- liblangutil/CMakeLists.txt | 2 + liblangutil/DebugInfoSelection.cpp | 157 +++++++++++++++++++++++++++++ liblangutil/DebugInfoSelection.h | 86 ++++++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 liblangutil/DebugInfoSelection.cpp create mode 100644 liblangutil/DebugInfoSelection.h diff --git a/liblangutil/CMakeLists.txt b/liblangutil/CMakeLists.txt index 28216207c..626d2945a 100644 --- a/liblangutil/CMakeLists.txt +++ b/liblangutil/CMakeLists.txt @@ -3,6 +3,8 @@ set(sources Common.h CharStream.cpp CharStream.h + DebugInfoSelection.cpp + DebugInfoSelection.h ErrorReporter.cpp ErrorReporter.h EVMVersion.h diff --git a/liblangutil/DebugInfoSelection.cpp b/liblangutil/DebugInfoSelection.cpp new file mode 100644 index 000000000..6ff023c01 --- /dev/null +++ b/liblangutil/DebugInfoSelection.cpp @@ -0,0 +1,157 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +using namespace std; +using namespace solidity; +using namespace solidity::langutil; +using namespace solidity::util; + +DebugInfoSelection const DebugInfoSelection::All(bool _value) noexcept +{ + DebugInfoSelection result; + for (bool DebugInfoSelection::* member: componentMap() | ranges::views::values) + result.*member = _value; + return result; +} + +DebugInfoSelection const DebugInfoSelection::Only(bool DebugInfoSelection::* _member) noexcept +{ + DebugInfoSelection result{}; + result.*_member = true; + return result; +} + +optional DebugInfoSelection::fromString(string_view _input) +{ + // TODO: Make more stuff constexpr and make it a static_assert(). + solAssert(componentMap().count("all") == 0, ""); + solAssert(componentMap().count("none") == 0, ""); + + if (_input == "all") + return All(); + if (_input == "none") + return None(); + + return fromComponents(_input | ranges::views::split(',') | ranges::to>); +} + +optional DebugInfoSelection::fromComponents( + vector const& _componentNames, + bool _acceptWildcards +) +{ + solAssert(componentMap().count("*") == 0, ""); + + DebugInfoSelection selection; + for (auto const& component: _componentNames) + { + if (component == "*") + return (_acceptWildcards ? make_optional(DebugInfoSelection::All()) : nullopt); + + if (!selection.enable(component)) + return nullopt; + } + + return selection; +} + +bool DebugInfoSelection::enable(string _component) +{ + auto memberIt = componentMap().find(boost::trim_copy(_component)); + if (memberIt == componentMap().end()) + return false; + + this->*(memberIt->second) = true; + return true; +} + +bool DebugInfoSelection::any() const noexcept +{ + for (bool DebugInfoSelection::* member: componentMap() | ranges::views::values) + if (this->*member) + return true; + + return false; +} + +bool DebugInfoSelection::all() const noexcept +{ + for (bool DebugInfoSelection::* member: componentMap() | ranges::views::values) + if (!(this->*member)) + return false; + + return true; +} + +DebugInfoSelection& DebugInfoSelection::operator&=(DebugInfoSelection const& _other) +{ + for (bool DebugInfoSelection::* member: componentMap() | ranges::views::values) + this->*member &= _other.*member; + return *this; +} + +DebugInfoSelection& DebugInfoSelection::operator|=(DebugInfoSelection const& _other) +{ + for (bool DebugInfoSelection::* member: componentMap() | ranges::views::values) + this->*member |= _other.*member; + return *this; +} + +DebugInfoSelection DebugInfoSelection::operator&(DebugInfoSelection _other) const noexcept +{ + _other &= *this; + return _other; +} + +DebugInfoSelection DebugInfoSelection::operator|(DebugInfoSelection _other) const noexcept +{ + _other |= *this; + return _other; +} + +bool DebugInfoSelection::operator==(DebugInfoSelection const& _other) const noexcept +{ + for (bool DebugInfoSelection::* member: componentMap() | ranges::views::values) + if (this->*member != _other.*member) + return false; + return true; +} + +ostream& langutil::operator<<(ostream& _stream, DebugInfoSelection const& _selection) +{ + vector selectedComponentNames; + for (auto const& [name, member]: _selection.componentMap()) + if (_selection.*member) + selectedComponentNames.push_back(name); + + return _stream << joinHumanReadable(selectedComponentNames, ","); +} diff --git a/liblangutil/DebugInfoSelection.h b/liblangutil/DebugInfoSelection.h new file mode 100644 index 000000000..40ba3d6b2 --- /dev/null +++ b/liblangutil/DebugInfoSelection.h @@ -0,0 +1,86 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 +/** + * Handles selections of debug info components. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace solidity::langutil +{ + +/** + * Represents a set of flags corresponding to components of debug info selected for some purpose. + * + * Provides extra functionality for enumerating the components and serializing/deserializing the + * selection to/from a comma-separated string. + */ +struct DebugInfoSelection +{ + static DebugInfoSelection const All(bool _value = true) noexcept; + static DebugInfoSelection const None() noexcept { return All(false); } + static DebugInfoSelection const Only(bool DebugInfoSelection::* _member) noexcept; + static DebugInfoSelection const Default() noexcept { return All(); } + + static std::optional fromString(std::string_view _input); + static std::optional fromComponents( + std::vector const& _componentNames, + bool _acceptWildcards = false + ); + bool enable(std::string _component); + + bool all() const noexcept; + bool any() const noexcept; + bool none() const noexcept { return !any(); } + bool only(bool DebugInfoSelection::* _member) const noexcept { return *this == Only(_member); } + + DebugInfoSelection& operator&=(DebugInfoSelection const& _other); + DebugInfoSelection& operator|=(DebugInfoSelection const& _other); + DebugInfoSelection operator&(DebugInfoSelection _other) const noexcept; + DebugInfoSelection operator|(DebugInfoSelection _other) const noexcept; + + bool operator!=(DebugInfoSelection const& _other) const noexcept { return !(*this == _other); } + bool operator==(DebugInfoSelection const& _other) const noexcept; + + friend std::ostream& operator<<(std::ostream& _stream, DebugInfoSelection const& _selection); + + static auto const& componentMap() + { + static std::map const components = { + {"location", &DebugInfoSelection::location}, + {"snippet", &DebugInfoSelection::snippet}, + {"ast-id", &DebugInfoSelection::astID}, + }; + return components; + } + + bool location = false; ///< Include source location. E.g. `@src 3:50:100` + bool snippet = false; ///< Include source code snippet next to location. E.g. `@src 3:50:100 "contract C {..."` + bool astID = false; ///< Include ID of the Solidity AST node. E.g. `@ast-id 15` +}; + +std::ostream& operator<<(std::ostream& _stream, DebugInfoSelection const& _selection); + +} From f7c4ed849d4fdcc28c09da18ef69d9dbaf3711b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 3 Sep 2021 19:38:59 +0200 Subject: [PATCH 27/62] Handle DebugInfoSelection in the code printing Yul and EVM assembly --- libevmasm/Assembly.cpp | 49 +++++++++++++------ libevmasm/Assembly.h | 3 ++ libsolidity/codegen/ir/Common.cpp | 6 ++- libsolidity/codegen/ir/IRGenerationContext.h | 3 ++ libsolidity/codegen/ir/IRGenerator.cpp | 50 +++++++++++++------- libsolidity/interface/CompilerStack.cpp | 2 +- libyul/AsmPrinter.cpp | 16 +++++-- libyul/AsmPrinter.h | 2 + 8 files changed, 96 insertions(+), 35 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 7884dd191..82bf2be71 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -96,13 +96,13 @@ public: m_out(_out), m_prefix(_prefix), m_sourceCodes(_sourceCodes), m_assembly(_assembly) {} - void feed(AssemblyItem const& _item) + void feed(AssemblyItem const& _item, DebugInfoSelection const& _debugInfoSelection) { if (_item.location().isValid() && _item.location() != m_location) { flush(); m_location = _item.location(); - printLocation(); + printLocation(_debugInfoSelection); } string expression = _item.toAssemblyText(m_assembly); @@ -142,16 +142,29 @@ public: m_pending.clear(); } - void printLocation() + void printLocation(DebugInfoSelection const& _debugInfoSelection) { - if (!m_location.isValid()) + if (!m_location.isValid() || (!_debugInfoSelection.location && !_debugInfoSelection.snippet)) return; + m_out << m_prefix << " /*"; - if (m_location.sourceName) - m_out << " " + escapeAndQuoteString(*m_location.sourceName); - if (m_location.hasText()) - m_out << ":" << to_string(m_location.start) + ":" + to_string(m_location.end); - m_out << " " << locationFromSources(m_sourceCodes, m_location); + + if (_debugInfoSelection.location) + { + if (m_location.sourceName) + m_out << " " + escapeAndQuoteString(*m_location.sourceName); + if (m_location.hasText()) + m_out << ":" << to_string(m_location.start) + ":" + to_string(m_location.end); + } + + if (_debugInfoSelection.snippet) + { + if (_debugInfoSelection.location) + m_out << " "; + + m_out << locationFromSources(m_sourceCodes, m_location); + } + m_out << " */" << endl; } @@ -167,12 +180,17 @@ private: } -void Assembly::assemblyStream(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const +void Assembly::assemblyStream( + ostream& _out, + DebugInfoSelection const& _debugInfoSelection, + string const& _prefix, + StringMap const& _sourceCodes +) const { Functionalizer f(_out, _prefix, _sourceCodes, *this); for (auto const& i: m_items) - f.feed(i); + f.feed(i, _debugInfoSelection); f.flush(); if (!m_data.empty() || !m_subs.empty()) @@ -185,7 +203,7 @@ void Assembly::assemblyStream(ostream& _out, string const& _prefix, StringMap co for (size_t i = 0; i < m_subs.size(); ++i) { _out << endl << _prefix << "sub_" << i << ": assembly {\n"; - m_subs[i]->assemblyStream(_out, _prefix + " ", _sourceCodes); + m_subs[i]->assemblyStream(_out, _debugInfoSelection, _prefix + " ", _sourceCodes); _out << _prefix << "}" << endl; } } @@ -194,10 +212,13 @@ void Assembly::assemblyStream(ostream& _out, string const& _prefix, StringMap co _out << endl << _prefix << "auxdata: 0x" << util::toHex(m_auxiliaryData) << endl; } -string Assembly::assemblyString(StringMap const& _sourceCodes) const +string Assembly::assemblyString( + DebugInfoSelection const& _debugInfoSelection, + StringMap const& _sourceCodes +) const { ostringstream tmp; - assemblyStream(tmp, "", _sourceCodes); + assemblyStream(tmp, _debugInfoSelection, "", _sourceCodes); return tmp.str(); } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 1d91c2f90..b532834f5 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -142,10 +143,12 @@ public: /// Create a text representation of the assembly. std::string assemblyString( + langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), StringMap const& _sourceCodes = StringMap() ) const; void assemblyStream( std::ostream& _out, + langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), std::string const& _prefix = "", StringMap const& _sourceCodes = StringMap() ) const; diff --git a/libsolidity/codegen/ir/Common.cpp b/libsolidity/codegen/ir/Common.cpp index 49a6be5e5..e75e5ef27 100644 --- a/libsolidity/codegen/ir/Common.cpp +++ b/libsolidity/codegen/ir/Common.cpp @@ -135,11 +135,15 @@ string dispenseLocationComment(langutil::SourceLocation const& _location, IRGene { solAssert(_location.sourceName, ""); _context.markSourceUsed(*_location.sourceName); - return "/// " + AsmPrinter::formatSourceLocation( + + string debugInfo = AsmPrinter::formatSourceLocation( _location, _context.sourceIndices(), + _context.debugInfoSelection(), _context.soliditySourceProvider() ); + + return debugInfo.empty() ? "" : "/// " + debugInfo; } string dispenseLocationComment(ASTNode const& _node, IRGenerationContext& _context) diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index fdc617220..8ceb8448f 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -174,6 +175,7 @@ public: bool immutableRegistered(VariableDeclaration const& _varDecl) const { return m_immutableVariables.count(&_varDecl); } + langutil::DebugInfoSelection debugInfoSelection() const { return m_debugInfoSelection; } langutil::CharStreamProvider const* soliditySourceProvider() const { return m_soliditySourceProvider; } private: @@ -220,6 +222,7 @@ private: std::set m_subObjects; + langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default(); langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr; }; diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index c1bfce4e3..1f8fe32a0 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -340,8 +340,7 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function) return m_context.functionCollector().createFunction(functionName, [&]() { m_context.resetLocalVariables(); Whiskers t(R"( - /// @ast-id - + function () -> { @@ -349,7 +348,10 @@ string IRGenerator::generateFunction(FunctionDefinition const& _function) )"); - t("astID", to_string(_function.id())); + if (m_context.debugInfoSelection().astID) + t("astIDComment", "/// @ast-id " + to_string(_function.id()) + "\n"); + else + t("astIDComment", ""); t("sourceLocationComment", dispenseLocationComment(_function)); t( "contractSourceLocationComment", @@ -409,8 +411,7 @@ string IRGenerator::generateModifier( return m_context.functionCollector().createFunction(functionName, [&]() { m_context.resetLocalVariables(); Whiskers t(R"( - /// @ast-id - + function () -> { @@ -418,6 +419,7 @@ string IRGenerator::generateModifier( } )"); + t("functionName", functionName); vector retParamsIn; for (auto const& varDecl: _function.returnParameters()) @@ -440,7 +442,11 @@ string IRGenerator::generateModifier( _modifierInvocation.name().annotation().referencedDeclaration ); solAssert(modifier, ""); - t("astID", to_string(modifier->id())); + + if (m_context.debugInfoSelection().astID) + t("astIDComment", "/// @ast-id " + to_string(modifier->id()) + "\n"); + else + t("astIDComment", ""); t("sourceLocationComment", dispenseLocationComment(*modifier)); t( "contractSourceLocationComment", @@ -546,14 +552,18 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) solAssert(paramTypes.empty(), ""); solUnimplementedAssert(type->sizeOnStack() == 1); return Whiskers(R"( - /// @ast-id - + function () -> rval { rval := loadimmutable("") } )") - ("astID", to_string(_varDecl.id())) + ( + "astIDComment", + m_context.debugInfoSelection().astID ? + "/// @ast-id " + to_string(_varDecl.id()) + "\n" : + "" + ) ("sourceLocationComment", dispenseLocationComment(_varDecl)) ( "contractSourceLocationComment", @@ -567,14 +577,18 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) { solAssert(paramTypes.empty(), ""); return Whiskers(R"( - /// @ast-id - + function () -> { := () } )") - ("astID", to_string(_varDecl.id())) + ( + "astIDComment", + m_context.debugInfoSelection().astID ? + "/// @ast-id " + to_string(_varDecl.id()) + "\n" : + "" + ) ("sourceLocationComment", dispenseLocationComment(_varDecl)) ( "contractSourceLocationComment", @@ -691,8 +705,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) } return Whiskers(R"( - /// @ast-id - + function () -> { } @@ -702,7 +715,12 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl) ("params", joinHumanReadable(parameters)) ("retVariables", joinHumanReadable(returnVariables)) ("code", std::move(code)) - ("astID", to_string(_varDecl.id())) + ( + "astIDComment", + m_context.debugInfoSelection().astID ? + "/// @ast-id " + to_string(_varDecl.id()) + "\n" : + "" + ) ("sourceLocationComment", dispenseLocationComment(_varDecl)) ( "contractSourceLocationComment", @@ -829,7 +847,7 @@ void IRGenerator::generateConstructors(ContractDefinition const& _contract) for (ASTPointer const& varDecl: contract->constructor()->parameters()) params += m_context.addLocalVariable(*varDecl).stackSlots(); - if (contract->constructor()) + if (m_context.debugInfoSelection().astID && contract->constructor()) t("astIDComment", "/// @ast-id " + to_string(contract->constructor()->id()) + "\n"); else t("astIDComment", ""); diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index e49c15387..8ef1abf32 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -882,7 +882,7 @@ string CompilerStack::assemblyString(string const& _contractName, StringMap cons Contract const& currentContract = contract(_contractName); if (currentContract.evmAssembly) - return currentContract.evmAssembly->assemblyString(_sourceCodes); + return currentContract.evmAssembly->assemblyString(DebugInfoSelection::Default(), _sourceCodes); else return string(); } diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 68f21bcd7..8cf5d6c11 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -261,10 +261,16 @@ string AsmPrinter::appendTypeName(YulString _type, bool _isBoolLiteral) const string AsmPrinter::formatSourceLocation( SourceLocation const& _location, map const& _nameToSourceIndex, + DebugInfoSelection const& _debugInfoSelection, CharStreamProvider const* _soliditySourceProvider ) { yulAssert(!_nameToSourceIndex.empty(), ""); + if (_debugInfoSelection.snippet) + yulAssert(_debugInfoSelection.location, "@src tag must always contain the source location"); + + if (_debugInfoSelection.none()) + return ""; string sourceIndex = "-1"; string solidityCodeSnippet = ""; @@ -272,7 +278,7 @@ string AsmPrinter::formatSourceLocation( { sourceIndex = to_string(_nameToSourceIndex.at(*_location.sourceName)); - if (_soliditySourceProvider) + if (_debugInfoSelection.snippet && _soliditySourceProvider) { solidityCodeSnippet = escapeAndQuoteString( _soliditySourceProvider->charStream(*_location.sourceName).singleLineSnippet(_location) @@ -298,12 +304,15 @@ string AsmPrinter::formatSourceLocation( string AsmPrinter::formatDebugData(shared_ptr const& _debugData, bool _statement) { - if (!_debugData) + DebugInfoSelection debugInfoSelection = DebugInfoSelection::Default(); + + if (!_debugData || debugInfoSelection.none()) return ""; vector items; if (auto id = _debugData->astID) - items.emplace_back("@ast-id " + to_string(*id)); + if (debugInfoSelection.astID) + items.emplace_back("@ast-id " + to_string(*id)); if ( m_lastLocation != _debugData->originLocation && @@ -315,6 +324,7 @@ string AsmPrinter::formatDebugData(shared_ptr const& _debugData items.emplace_back(formatSourceLocation( _debugData->originLocation, m_nameToSourceIndex, + debugInfoSelection, m_soliditySourceProvider )); } diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 3bb683191..94890fa15 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -83,6 +84,7 @@ public: static std::string formatSourceLocation( langutil::SourceLocation const& _location, std::map const& _nameToSourceIndex, + langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr ); From bcfefc79d9dde1f4eaff318189b73962a86b2a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 17 Sep 2021 20:15:19 +0200 Subject: [PATCH 28/62] Pass DebugInfoSelection down to the code handling assembly printing --- libsolidity/codegen/ir/IRGenerationContext.h | 4 ++- libsolidity/codegen/ir/IRGenerator.cpp | 8 +++++- libsolidity/codegen/ir/IRGenerator.h | 2 ++ libsolidity/interface/CompilerStack.cpp | 25 ++++++++++++++++--- libsolidity/interface/CompilerStack.h | 7 +++++- libsolidity/interface/StandardCompiler.cpp | 10 ++++++-- libyul/AsmPrinter.cpp | 8 +++--- libyul/AsmPrinter.h | 7 ++++-- libyul/AssemblyStack.cpp | 10 +++++--- libyul/AssemblyStack.h | 24 +++++++++++++++--- libyul/Object.cpp | 12 ++++++--- libyul/Object.h | 4 +++ solc/CommandLineInterface.cpp | 3 ++- test/libsolidity/InlineAssembly.cpp | 22 +++++++++++++--- .../SolidityExecutionFramework.cpp | 10 ++++++-- test/libyul/Common.cpp | 4 ++- test/libyul/EVMCodeTransformTest.cpp | 7 +++++- test/libyul/EwasmTranslationTest.cpp | 4 ++- test/libyul/ObjectCompilerTest.cpp | 4 ++- test/libyul/ObjectParser.cpp | 7 ++++-- test/libyul/YulInterpreterTest.cpp | 4 ++- test/tools/ossfuzz/YulEvmoneInterface.h | 5 +++- .../ossfuzz/strictasm_assembly_ossfuzz.cpp | 4 ++- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 4 ++- test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp | 6 ++++- test/tools/ossfuzz/yulProtoFuzzer.cpp | 4 ++- test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp | 4 ++- test/tools/yulrun.cpp | 4 ++- 28 files changed, 170 insertions(+), 47 deletions(-) diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 8ceb8448f..cf01dc4f4 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -75,6 +75,7 @@ public: RevertStrings _revertStrings, OptimiserSettings _optimiserSettings, std::map _sourceIndices, + langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ): m_evmVersion(_evmVersion), @@ -82,6 +83,7 @@ public: m_revertStrings(_revertStrings), m_optimiserSettings(std::move(_optimiserSettings)), m_sourceIndices(std::move(_sourceIndices)), + m_debugInfoSelection(_debugInfoSelection), m_soliditySourceProvider(_soliditySourceProvider) {} @@ -222,7 +224,7 @@ private: std::set m_subObjects; - langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default(); + langutil::DebugInfoSelection m_debugInfoSelection = {}; langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr; }; diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 1f8fe32a0..6a513a300 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -95,7 +95,12 @@ pair IRGenerator::run( { string const ir = yul::reindent(generate(_contract, _cborMetadata, _otherYulSources)); - yul::AssemblyStack asmStack(m_evmVersion, yul::AssemblyStack::Language::StrictAssembly, m_optimiserSettings); + yul::AssemblyStack asmStack( + m_evmVersion, + yul::AssemblyStack::Language::StrictAssembly, + m_optimiserSettings, + m_context.debugInfoSelection() + ); if (!asmStack.parseAndAnalyze("", ir)) { string errorMessage; @@ -1103,6 +1108,7 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon m_context.revertStrings(), m_optimiserSettings, m_context.sourceIndices(), + m_context.debugInfoSelection(), m_context.soliditySourceProvider() ); newContext.copyFunctionIDsFrom(m_context); diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index 85b570c7f..126f90046 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -49,6 +49,7 @@ public: RevertStrings _revertStrings, OptimiserSettings _optimiserSettings, std::map _sourceIndices, + langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ): m_evmVersion(_evmVersion), @@ -59,6 +60,7 @@ public: _revertStrings, std::move(_optimiserSettings), std::move(_sourceIndices), + _debugInfoSelection, _soliditySourceProvider ), m_utils(_evmVersion, m_context.revertStrings(), m_context.functionCollector()) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 8ef1abf32..71c701e40 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -271,6 +271,13 @@ void CompilerStack::setMetadataHash(MetadataHash _metadataHash) m_metadataHash = _metadataHash; } +void CompilerStack::selectDebugInfo(DebugInfoSelection _debugInfoSelection) +{ + if (m_stackState >= CompilationSuccessful) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must select debug info components before compilation.")); + m_debugInfoSelection = _debugInfoSelection; +} + void CompilerStack::addSMTLib2Response(h256 const& _hash, string const& _response) { if (m_stackState >= ParsedAndImported) @@ -882,7 +889,7 @@ string CompilerStack::assemblyString(string const& _contractName, StringMap cons Contract const& currentContract = contract(_contractName); if (currentContract.evmAssembly) - return currentContract.evmAssembly->assemblyString(DebugInfoSelection::Default(), _sourceCodes); + return currentContract.evmAssembly->assemblyString(m_debugInfoSelection, _sourceCodes); else return string(); } @@ -1319,7 +1326,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract) for (auto const& pair: m_contracts) otherYulSources.emplace(pair.second.contract, pair.second.yulIR); - IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings, sourceIndices(), this); + IRGenerator generator(m_evmVersion, m_revertStrings, m_optimiserSettings, sourceIndices(), m_debugInfoSelection, this); tie(compiledContract.yulIR, compiledContract.yulIROptimized) = generator.run( _contract, createCBORMetadata(compiledContract, /* _forIR */ true), @@ -1342,7 +1349,12 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) return; // Re-parse the Yul IR in EVM dialect - yul::AssemblyStack stack(m_evmVersion, yul::AssemblyStack::Language::StrictAssembly, m_optimiserSettings); + yul::AssemblyStack stack( + m_evmVersion, + yul::AssemblyStack::Language::StrictAssembly, + m_optimiserSettings, + m_debugInfoSelection + ); stack.parseAndAnalyze("", compiledContract.yulIROptimized); stack.optimize(); @@ -1369,7 +1381,12 @@ void CompilerStack::generateEwasm(ContractDefinition const& _contract) return; // Re-parse the Yul IR in EVM dialect - yul::AssemblyStack stack(m_evmVersion, yul::AssemblyStack::Language::StrictAssembly, m_optimiserSettings); + yul::AssemblyStack stack( + m_evmVersion, + yul::AssemblyStack::Language::StrictAssembly, + m_optimiserSettings, + m_debugInfoSelection + ); stack.parseAndAnalyze("", compiledContract.yulIROptimized); stack.optimize(); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index bbef4dc64..c97581a65 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -35,10 +35,11 @@ #include +#include +#include #include #include #include -#include #include @@ -203,6 +204,9 @@ public: /// @param _metadataHash can be IPFS, Bzzr1, None void setMetadataHash(MetadataHash _metadataHash); + /// Select components of debug info that should be included in comments in generated assembly. + void selectDebugInfo(langutil::DebugInfoSelection _debugInfoSelection); + /// Sets the sources. Must be set before parsing. void setSources(StringMap _sources); @@ -505,6 +509,7 @@ private: langutil::ErrorReporter m_errorReporter; bool m_metadataLiteralSources = false; MetadataHash m_metadataHash = MetadataHash::IPFS; + langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default(); bool m_parserErrorRecovery = false; State m_stackState = Empty; bool m_importedSources = false; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 446253f0a..240ad4f9c 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -28,9 +28,14 @@ #include #include #include -#include + #include + #include + +#include +#include + #include #include #include @@ -1358,7 +1363,8 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) AssemblyStack stack( _inputsAndSettings.evmVersion, AssemblyStack::Language::StrictAssembly, - _inputsAndSettings.optimiserSettings + _inputsAndSettings.optimiserSettings, + DebugInfoSelection::Default() ); string const& sourceName = _inputsAndSettings.sources.begin()->first; string const& sourceContents = _inputsAndSettings.sources.begin()->second; diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 8cf5d6c11..46000bc10 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -304,14 +304,12 @@ string AsmPrinter::formatSourceLocation( string AsmPrinter::formatDebugData(shared_ptr const& _debugData, bool _statement) { - DebugInfoSelection debugInfoSelection = DebugInfoSelection::Default(); - - if (!_debugData || debugInfoSelection.none()) + if (!_debugData || m_debugInfoSelection.none()) return ""; vector items; if (auto id = _debugData->astID) - if (debugInfoSelection.astID) + if (m_debugInfoSelection.astID) items.emplace_back("@ast-id " + to_string(*id)); if ( @@ -324,7 +322,7 @@ string AsmPrinter::formatDebugData(shared_ptr const& _debugData items.emplace_back(formatSourceLocation( _debugData->originLocation, m_nameToSourceIndex, - debugInfoSelection, + m_debugInfoSelection, m_soliditySourceProvider )); } diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 94890fa15..7c67c14ac 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -49,9 +49,11 @@ public: explicit AsmPrinter( Dialect const* _dialect = nullptr, std::optional>> _sourceIndexToName = {}, + langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ): m_dialect(_dialect), + m_debugInfoSelection(_debugInfoSelection), m_soliditySourceProvider(_soliditySourceProvider) { if (_sourceIndexToName) @@ -59,12 +61,12 @@ public: m_nameToSourceIndex[*name] = index; } - explicit AsmPrinter( Dialect const& _dialect, std::optional>> _sourceIndexToName = {}, + langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr - ): AsmPrinter(&_dialect, _sourceIndexToName, _soliditySourceProvider) {} + ): AsmPrinter(&_dialect, _sourceIndexToName, _debugInfoSelection, _soliditySourceProvider) {} std::string operator()(Literal const& _literal); std::string operator()(Identifier const& _identifier); @@ -102,6 +104,7 @@ private: Dialect const* const m_dialect = nullptr; std::map m_nameToSourceIndex; langutil::SourceLocation m_lastLocation = {}; + langutil::DebugInfoSelection m_debugInfoSelection = {}; langutil::CharStreamProvider const* m_soliditySourceProvider = nullptr; }; diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp index 1ed55a2d6..30ad58d77 100644 --- a/libyul/AssemblyStack.cpp +++ b/libyul/AssemblyStack.cpp @@ -249,7 +249,7 @@ AssemblyStack::assembleWithDeployed(optional _deployName) const MachineAssemblyObject creationObject; creationObject.bytecode = make_shared(creationAssembly->assemble()); yulAssert(creationObject.bytecode->immutableReferences.empty(), "Leftover immutables."); - creationObject.assembly = creationAssembly->assemblyString(); + creationObject.assembly = creationAssembly->assemblyString(m_debugInfoSelection); creationObject.sourceMappings = make_unique( evmasm::AssemblyItem::computeSourceMapping( creationAssembly->items(), @@ -261,7 +261,7 @@ AssemblyStack::assembleWithDeployed(optional _deployName) const if (deployedAssembly) { deployedObject.bytecode = make_shared(deployedAssembly->assemble()); - deployedObject.assembly = deployedAssembly->assemblyString(); + deployedObject.assembly = deployedAssembly->assemblyString(m_debugInfoSelection); deployedObject.sourceMappings = make_unique( evmasm::AssemblyItem::computeSourceMapping( deployedAssembly->items(), @@ -314,11 +314,13 @@ AssemblyStack::assembleEVMWithDeployed(optional _deployName) const return {make_shared(assembly), {}}; } -string AssemblyStack::print(CharStreamProvider const* _soliditySourceProvider) const +string AssemblyStack::print( + CharStreamProvider const* _soliditySourceProvider +) const { yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); - return m_parserResult->toString(&languageToDialect(m_language, m_evmVersion), _soliditySourceProvider) + "\n"; + return m_parserResult->toString(&languageToDialect(m_language, m_evmVersion), m_debugInfoSelection, _soliditySourceProvider) + "\n"; } shared_ptr AssemblyStack::parserResult() const diff --git a/libyul/AssemblyStack.h b/libyul/AssemblyStack.h index 91ca78af7..950265ca4 100644 --- a/libyul/AssemblyStack.h +++ b/libyul/AssemblyStack.h @@ -22,9 +22,10 @@ #pragma once +#include +#include #include #include -#include #include #include @@ -69,12 +70,24 @@ public: enum class Machine { EVM, Ewasm }; AssemblyStack(): - AssemblyStack(langutil::EVMVersion{}, Language::Assembly, solidity::frontend::OptimiserSettings::none()) + AssemblyStack( + langutil::EVMVersion{}, + Language::Assembly, + solidity::frontend::OptimiserSettings::none(), + langutil::DebugInfoSelection::Default() + ) {} - AssemblyStack(langutil::EVMVersion _evmVersion, Language _language, solidity::frontend::OptimiserSettings _optimiserSettings): + + AssemblyStack( + langutil::EVMVersion _evmVersion, + Language _language, + solidity::frontend::OptimiserSettings _optimiserSettings, + langutil::DebugInfoSelection const& _debugInfoSelection + ): m_language(_language), m_evmVersion(_evmVersion), m_optimiserSettings(std::move(_optimiserSettings)), + m_debugInfoSelection(_debugInfoSelection), m_errorReporter(m_errors) {} @@ -116,7 +129,9 @@ public: langutil::ErrorList const& errors() const { return m_errors; } /// Pretty-print the input after having parsed it. - std::string print(langutil::CharStreamProvider const* _soliditySourceProvider = nullptr) const; + std::string print( + langutil::CharStreamProvider const* _soliditySourceProvider = nullptr + ) const; /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; @@ -132,6 +147,7 @@ private: Language m_language = Language::Assembly; langutil::EVMVersion m_evmVersion; solidity::frontend::OptimiserSettings m_optimiserSettings; + langutil::DebugInfoSelection m_debugInfoSelection{}; std::unique_ptr m_charStream; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index eee016aa4..ed456ab53 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -51,13 +51,14 @@ string indent(std::string const& _input) } -string Data::toString(Dialect const*, CharStreamProvider const*) const +string Data::toString(Dialect const*, DebugInfoSelection const&, CharStreamProvider const*) const { return "data \"" + name.str() + "\" hex\"" + util::toHex(data) + "\""; } string Object::toString( Dialect const* _dialect, + DebugInfoSelection const& _debugInfoSelection, CharStreamProvider const* _soliditySourceProvider ) const { @@ -74,10 +75,15 @@ string Object::toString( })) + "\n"; - string inner = "code " + AsmPrinter{_dialect, debugData->sourceNames, _soliditySourceProvider}(*code); + string inner = "code " + AsmPrinter( + _dialect, + debugData->sourceNames, + _debugInfoSelection, + _soliditySourceProvider + )(*code); for (auto const& obj: subObjects) - inner += "\n" + obj->toString(_dialect, _soliditySourceProvider); + inner += "\n" + obj->toString(_dialect, _debugInfoSelection, _soliditySourceProvider); return useSrcComment + "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; } diff --git a/libyul/Object.h b/libyul/Object.h index 1b08821ce..f3c4ee34a 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -25,6 +25,7 @@ #include #include +#include #include @@ -54,6 +55,7 @@ struct ObjectNode YulString name; virtual std::string toString( Dialect const* _dialect, + langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const = 0; }; @@ -69,6 +71,7 @@ struct Data: public ObjectNode std::string toString( Dialect const* _dialect, + langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const override; }; @@ -89,6 +92,7 @@ public: /// @returns a (parseable) string representation. std::string toString( Dialect const* _dialect, + langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ) const; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index a825dd2a4..e1a0b3dbe 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -972,7 +972,8 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul: auto& stack = assemblyStacks[src.first] = yul::AssemblyStack( m_options.output.evmVersion, _language, - m_options.optimiserSettings() + m_options.optimiserSettings(), + DebugInfoSelection::Default() ); if (!stack.parseAndAnalyze(src.first, src.second)) diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 7e539051d..f0e5e455f 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -28,6 +28,7 @@ #include +#include #include #include #include @@ -59,7 +60,12 @@ std::optional parseAndReturnFirstError( AssemblyStack::Machine _machine = AssemblyStack::Machine::EVM ) { - AssemblyStack stack(solidity::test::CommonOptions::get().evmVersion(), _language, solidity::frontend::OptimiserSettings::none()); + AssemblyStack stack( + solidity::test::CommonOptions::get().evmVersion(), + _language, + solidity::frontend::OptimiserSettings::none(), + DebugInfoSelection::None() + ); bool success = false; try { @@ -125,7 +131,12 @@ Error expectError( void parsePrintCompare(string const& _source, bool _canWarn = false) { - AssemblyStack stack(solidity::test::CommonOptions::get().evmVersion(), AssemblyStack::Language::Assembly, OptimiserSettings::none()); + AssemblyStack stack( + solidity::test::CommonOptions::get().evmVersion(), + AssemblyStack::Language::Assembly, + OptimiserSettings::none(), + DebugInfoSelection::None() + ); BOOST_REQUIRE(stack.parseAndAnalyze("", _source)); if (_canWarn) BOOST_REQUIRE(!Error::containsErrors(stack.errors())); @@ -210,7 +221,12 @@ BOOST_AUTO_TEST_CASE(print_string_literal_unicode) { string source = "{ let x := \"\\u1bac\" }"; string parsed = "object \"object\" {\n code { let x := \"\\xe1\\xae\\xac\" }\n}\n"; - AssemblyStack stack(solidity::test::CommonOptions::get().evmVersion(), AssemblyStack::Language::Assembly, OptimiserSettings::none()); + AssemblyStack stack( + solidity::test::CommonOptions::get().evmVersion(), + AssemblyStack::Language::Assembly, + OptimiserSettings::none(), + DebugInfoSelection::None() + ); BOOST_REQUIRE(stack.parseAndAnalyze("", source)); BOOST_REQUIRE(stack.errors().empty()); BOOST_CHECK_EQUAL(stack.print(), parsed); diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 95f0ba1ef..f3921613f 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -23,6 +23,7 @@ #include +#include #include #include @@ -34,6 +35,7 @@ using namespace solidity; using namespace solidity::frontend; using namespace solidity::frontend::test; +using namespace solidity::langutil; using namespace solidity::test; using namespace std; @@ -94,8 +96,12 @@ bytes SolidityExecutionFramework::multiSourceCompileContract( else if (forceEnableOptimizer) optimiserSettings = OptimiserSettings::full(); - yul::AssemblyStack - asmStack(m_evmVersion, yul::AssemblyStack::Language::StrictAssembly, optimiserSettings); + yul::AssemblyStack asmStack( + m_evmVersion, + yul::AssemblyStack::Language::StrictAssembly, + optimiserSettings, + DebugInfoSelection::All() + ); bool analysisSuccessful = asmStack.parseAndAnalyze("", m_compiler.yulIROptimized(contractName)); solAssert(analysisSuccessful, "Code that passed analysis in CompilerStack can't have errors"); diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 8e5dc55e6..fc9be2001 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -59,7 +60,8 @@ pair, shared_ptr> yul::test::parse(strin _yul ? AssemblyStack::Language::Yul : AssemblyStack::Language::StrictAssembly, solidity::test::CommonOptions::get().optimize ? solidity::frontend::OptimiserSettings::standard() : - solidity::frontend::OptimiserSettings::minimal() + solidity::frontend::OptimiserSettings::minimal(), + DebugInfoSelection::All() ); if (!stack.parseAndAnalyze("", _source) || !stack.errors().empty()) BOOST_FAIL("Invalid source."); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 043eae331..38ef5ad39 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -47,7 +47,12 @@ TestCase::TestResult EVMCodeTransformTest::run(ostream& _stream, string const& _ solidity::frontend::OptimiserSettings settings = solidity::frontend::OptimiserSettings::none(); settings.runYulOptimiser = false; settings.optimizeStackAllocation = m_stackOpt; - AssemblyStack stack(EVMVersion{}, AssemblyStack::Language::StrictAssembly, settings); + AssemblyStack stack( + EVMVersion{}, + AssemblyStack::Language::StrictAssembly, + settings, + DebugInfoSelection::All() + ); if (!stack.parseAndAnalyze("", m_source)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; diff --git a/test/libyul/EwasmTranslationTest.cpp b/test/libyul/EwasmTranslationTest.cpp index 6051c2e20..9bd80f4b1 100644 --- a/test/libyul/EwasmTranslationTest.cpp +++ b/test/libyul/EwasmTranslationTest.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -82,7 +83,8 @@ bool EwasmTranslationTest::parse(ostream& _stream, string const& _linePrefix, bo m_stack = AssemblyStack( solidity::test::CommonOptions::get().evmVersion(), AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none() + solidity::frontend::OptimiserSettings::none(), + DebugInfoSelection::All() ); if (m_stack.parseAndAnalyze("", m_source)) { diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index 37b1688a9..256bced21 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -26,6 +26,7 @@ #include +#include #include #include @@ -64,7 +65,8 @@ TestCase::TestResult ObjectCompilerTest::run(ostream& _stream, string const& _li AssemblyStack stack( EVMVersion(), m_wasm ? AssemblyStack::Language::Ewasm : AssemblyStack::Language::StrictAssembly, - OptimiserSettings::preset(m_optimisationPreset) + OptimiserSettings::preset(m_optimisationPreset), + DebugInfoSelection::All() ); if (!stack.parseAndAnalyze("source", m_source)) { diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index d70d2002c..1d6f0bed3 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -23,6 +23,7 @@ #include +#include #include #include @@ -60,7 +61,8 @@ pair parse(string const& _source) AssemblyStack asmStack( solidity::test::CommonOptions::get().evmVersion(), AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none() + solidity::frontend::OptimiserSettings::none(), + DebugInfoSelection::All() ); bool success = asmStack.parseAndAnalyze("source", _source); return {success, asmStack.errors()}; @@ -181,7 +183,8 @@ BOOST_AUTO_TEST_CASE(to_string) AssemblyStack asmStack( solidity::test::CommonOptions::get().evmVersion(), AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none() + solidity::frontend::OptimiserSettings::none(), + DebugInfoSelection::All() ); BOOST_REQUIRE(asmStack.parseAndAnalyze("source", code)); BOOST_CHECK_EQUAL(asmStack.print(), expectation); diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index 6f7da9f98..ba47b4c08 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -67,7 +68,8 @@ bool YulInterpreterTest::parse(ostream& _stream, string const& _linePrefix, bool AssemblyStack stack( solidity::test::CommonOptions::get().evmVersion(), AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none() + solidity::frontend::OptimiserSettings::none(), + DebugInfoSelection::All() ); if (stack.parseAndAnalyze("", m_source)) { diff --git a/test/tools/ossfuzz/YulEvmoneInterface.h b/test/tools/ossfuzz/YulEvmoneInterface.h index b7a430b60..0b3384940 100644 --- a/test/tools/ossfuzz/YulEvmoneInterface.h +++ b/test/tools/ossfuzz/YulEvmoneInterface.h @@ -23,6 +23,8 @@ #include +#include + namespace solidity::test::fuzzer { class YulAssembler @@ -36,7 +38,8 @@ public: m_stack( _version, solidity::yul::AssemblyStack::Language::StrictAssembly, - _optSettings + _optSettings, + langutil::DebugInfoSelection::All() ), m_yulProgram(_yulSource), m_optimiseYul(_optSettings.runYulOptimiser) diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index 97bf0aebc..7142ec23c 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -19,6 +19,7 @@ #include #include +#include #include using namespace solidity; @@ -39,7 +40,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) AssemblyStack stack( langutil::EVMVersion(), AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::full() + solidity::frontend::OptimiserSettings::full(), + langutil::DebugInfoSelection::All() ); if (!stack.parseAndAnalyze("source", input)) diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index 6c7bc61cb..a3a789bc9 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -61,7 +62,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) AssemblyStack stack( langutil::EVMVersion(), AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::full() + solidity::frontend::OptimiserSettings::full(), + DebugInfoSelection::All() ); try { diff --git a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp index b1aa9a21f..05a0179bf 100644 --- a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp @@ -17,9 +17,12 @@ // SPDX-License-Identifier: GPL-3.0 #include + +#include #include using namespace solidity; +using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; using namespace std; @@ -38,7 +41,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) AssemblyStack stack( langutil::EVMVersion(), AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::full() + solidity::frontend::OptimiserSettings::full(), + DebugInfoSelection::All() ); if (!stack.parseAndAnalyze("source", input)) diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index f44ddaaa1..ca15b3769 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -30,6 +30,7 @@ #include +#include #include #include @@ -64,7 +65,8 @@ DEFINE_PROTO_FUZZER(Program const& _input) AssemblyStack stack( version, AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::full() + solidity::frontend::OptimiserSettings::full(), + DebugInfoSelection::All() ); // Parse protobuf mutated YUL code diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index abb0df82f..22f67e1cf 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -63,7 +64,8 @@ DEFINE_PROTO_FUZZER(Program const& _input) AssemblyStack stack( version, AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::full() + solidity::frontend::OptimiserSettings::full(), + DebugInfoSelection::All() ); // Parse protobuf mutated YUL code diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index 7906be744..cb90a3f43 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -58,7 +59,8 @@ pair, shared_ptr> parse(string const& _source AssemblyStack stack( langutil::EVMVersion(), AssemblyStack::Language::StrictAssembly, - solidity::frontend::OptimiserSettings::none() + solidity::frontend::OptimiserSettings::none(), + DebugInfoSelection::Default() ); if (stack.parseAndAnalyze("--INPUT--", _source)) { From a9e794c87242e6eb5d2e07862dfca2cd4afafbec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 13 Sep 2021 14:17:05 +0200 Subject: [PATCH 29/62] Expose --debug-info/settings.debug.debugInfo option --- Changelog.md | 2 + docs/using-the-compiler.rst | 13 +- libsolidity/interface/StandardCompiler.cpp | 34 ++- libsolidity/interface/StandardCompiler.h | 3 + solc/CommandLineInterface.cpp | 6 +- solc/CommandLineParser.cpp | 32 +++ solc/CommandLineParser.h | 5 + .../args | 1 + .../input.sol | 6 + .../output | 213 ++++++++++++++++ .../args | 1 + .../err | 1 + .../exit | 1 + .../input.sol | 0 .../args | 1 + .../input.sol | 6 + .../output | 212 ++++++++++++++++ .../args | 1 + .../input.sol | 6 + .../output | 201 +++++++++++++++ .../args | 1 + .../err | 1 + .../exit | 1 + .../input.sol | 6 + .../args | 1 + .../in.sol | 6 + .../input.json | 13 + .../output.json | 230 ++++++++++++++++++ .../args | 1 + .../in.sol | 6 + .../input.json | 13 + .../output.json | 229 +++++++++++++++++ .../args | 1 + .../in.sol | 6 + .../input.json | 13 + .../output.json | 218 +++++++++++++++++ .../args | 1 + .../in.sol | 6 + .../input.json | 13 + .../output.json | 12 + .../standard_yul_debug_info_print_all/args | 1 + .../standard_yul_debug_info_print_all/in.yul | 15 ++ .../input.json | 12 + .../output.json | 36 +++ .../args | 1 + .../in.yul | 15 ++ .../input.json | 12 + .../output.json | 36 +++ .../standard_yul_debug_info_print_none/args | 1 + .../standard_yul_debug_info_print_none/in.yul | 15 ++ .../input.json | 12 + .../output.json | 34 +++ .../args | 1 + .../in.yul | 15 ++ .../input.json | 12 + .../output.json | 12 + .../strict_asm_debug_info_print_all/args | 1 + .../strict_asm_debug_info_print_all/err | 1 + .../strict_asm_debug_info_print_all/input.yul | 15 ++ .../strict_asm_debug_info_print_all/output | 32 +++ .../args | 1 + .../err | 1 + .../input.yul | 15 ++ .../output | 32 +++ .../strict_asm_debug_info_print_none/args | 1 + .../strict_asm_debug_info_print_none/err | 1 + .../input.yul | 15 ++ .../strict_asm_debug_info_print_none/output | 28 +++ .../args | 1 + .../err | 1 + .../exit | 1 + .../input.yul | 15 ++ test/solc/CommandLineParser.cpp | 4 + 73 files changed, 1913 insertions(+), 5 deletions(-) create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/args create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/input.sol create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/args create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/err create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/exit create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/input.sol create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/args create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/input.sol create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/args create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/input.sol create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/args create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/err create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/exit create mode 100644 test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/input.sol create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/args create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/in.sol create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/input.json create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/args create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/in.sol create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/input.json create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/args create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/in.sol create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/input.json create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/args create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/in.sol create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/input.json create mode 100644 test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/output.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_all/args create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_all/in.yul create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_all/input.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_all/output.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_location_only/args create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_location_only/in.yul create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_location_only/input.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_location_only/output.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_none/args create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_none/in.yul create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_none/input.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_none/output.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_snippet_only/args create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_snippet_only/in.yul create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_snippet_only/input.json create mode 100644 test/cmdlineTests/standard_yul_debug_info_print_snippet_only/output.json create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_all/args create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_all/err create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_all/input.yul create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_all/output create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_location_only/args create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_location_only/err create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_location_only/input.yul create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_location_only/output create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_none/args create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_none/err create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_none/input.yul create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_none/output create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_snippet_only/args create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_snippet_only/err create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_snippet_only/exit create mode 100644 test/cmdlineTests/strict_asm_debug_info_print_snippet_only/input.yul diff --git a/Changelog.md b/Changelog.md index 9dd650599..24b326a12 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,8 +6,10 @@ Language Features: Compiler Features: * Commandline Interface: Accept nested brackets in step sequences passed to ``--yul-optimizations``. + * Commandline Interface: Add ``--debug-info`` option for selecting how much extra debug information should be included in the produced EVM assembly and Yul code. * SMTChecker: Output values for ``block.*``, ``msg.*`` and ``tx.*`` variables that are present in the called functions. * Standard JSON: Accept nested brackets in step sequences passed to ``settings.optimizer.details.yulDetails.optimizerSteps``. + * Standard JSON: Add ``settings.debug.debugInfo`` option for selecting how much extra debug information should be included in the produced EVM assembly and Yul code. Bugfixes: diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 1b14187ca..88da5d5e6 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -308,7 +308,18 @@ Input Description // "strip" removes all revert strings (if possible, i.e. if literals are used) keeping side-effects // "debug" injects strings for compiler-generated internal reverts, implemented for ABI encoders V1 and V2 for now. // "verboseDebug" even appends further information to user-supplied revert strings (not yet implemented) - "revertStrings": "default" + "revertStrings": "default", + // Optional: How much extra debug information to include in comments in the produced EVM + // assembly and Yul code. Available components are: + // - `location`: Annotations of the form `@src ::` indicating the + // location of the corresponding element in the original Solidity file, where: + // - `` is the file index matching the `@use-src` annotation, + // - `` is the index of the first byte at that location, + // - `` is the index of the first byte after that location. + // - `snippet`: A single-line code snippet from the location indicated by `@src`. + // The snippet is quoted and follows the corresponding `@src` annotation. + // - `*`: Wildcard value that can be used to request everything. + "debugInfo": ["location", "snippet"] }, // Metadata settings (optional) "metadata": { diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 240ad4f9c..66f5dc4e5 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -33,7 +33,6 @@ #include -#include #include #include @@ -798,7 +797,7 @@ std::variant StandardCompiler: if (settings.isMember("debug")) { - if (auto result = checkKeys(settings["debug"], {"revertStrings"}, "settings.debug")) + if (auto result = checkKeys(settings["debug"], {"revertStrings", "debugInfo"}, "settings.debug")) return *result; if (settings["debug"].isMember("revertStrings")) @@ -815,6 +814,31 @@ std::variant StandardCompiler: ); ret.revertStrings = *revertStrings; } + + if (settings["debug"].isMember("debugInfo")) + { + if (!settings["debug"]["debugInfo"].isArray()) + return formatFatalError("JSONError", "settings.debug.debugInfo must be an array."); + + vector components; + for (Json::Value const& arrayValue: settings["debug"]["debugInfo"]) + components.push_back(arrayValue.asString()); + + optional debugInfoSelection = DebugInfoSelection::fromComponents( + components, + true /* _acceptWildcards */ + ); + if (!debugInfoSelection.has_value()) + return formatFatalError("JSONError", "Invalid value in settings.debug.debugInfo."); + + if (debugInfoSelection->snippet && !debugInfoSelection->location) + return formatFatalError( + "JSONError", + "To use 'snippet' with settings.debug.debugInfo you must select also 'location'." + ); + + ret.debugInfoSelection = debugInfoSelection.value(); + } } if (settings.isMember("remappings") && !settings["remappings"].isArray()) @@ -1034,6 +1058,8 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting compilerStack.setRemappings(move(_inputsAndSettings.remappings)); compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings)); compilerStack.setRevertStringBehaviour(_inputsAndSettings.revertStrings); + if (_inputsAndSettings.debugInfoSelection.has_value()) + compilerStack.selectDebugInfo(_inputsAndSettings.debugInfoSelection.value()); compilerStack.setLibraries(_inputsAndSettings.libraries); compilerStack.useMetadataLiteralSources(_inputsAndSettings.metadataLiteralSources); compilerStack.setMetadataHash(_inputsAndSettings.metadataHash); @@ -1364,7 +1390,9 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) _inputsAndSettings.evmVersion, AssemblyStack::Language::StrictAssembly, _inputsAndSettings.optimiserSettings, - DebugInfoSelection::Default() + _inputsAndSettings.debugInfoSelection.has_value() ? + _inputsAndSettings.debugInfoSelection.value() : + DebugInfoSelection::Default() ); string const& sourceName = _inputsAndSettings.sources.begin()->first; string const& sourceContents = _inputsAndSettings.sources.begin()->second; diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h index 4d43fdfec..679e731a2 100644 --- a/libsolidity/interface/StandardCompiler.h +++ b/libsolidity/interface/StandardCompiler.h @@ -26,6 +26,8 @@ #include #include +#include + #include #include #include @@ -78,6 +80,7 @@ private: std::vector remappings; RevertStrings revertStrings = RevertStrings::Default; OptimiserSettings optimiserSettings = OptimiserSettings::minimal(); + std::optional debugInfoSelection; std::map libraries; bool metadataLiteralSources = false; CompilerStack::MetadataHash metadataHash = CompilerStack::MetadataHash::IPFS; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index e1a0b3dbe..3b26b6c83 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -631,6 +631,8 @@ bool CommandLineInterface::compile() m_compiler->setViaIR(m_options.output.experimentalViaIR); m_compiler->setEVMVersion(m_options.output.evmVersion); m_compiler->setRevertStringBehaviour(m_options.output.revertStrings); + if (m_options.output.debugInfoSelection.has_value()) + m_compiler->selectDebugInfo(m_options.output.debugInfoSelection.value()); // TODO: Perhaps we should not compile unless requested m_compiler->enableIRGeneration(m_options.compiler.outputs.ir || m_options.compiler.outputs.irOptimized); @@ -973,7 +975,9 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul: m_options.output.evmVersion, _language, m_options.optimiserSettings(), - DebugInfoSelection::Default() + m_options.output.debugInfoSelection.has_value() ? + m_options.output.debugInfoSelection.value() : + DebugInfoSelection::Default() ); if (!stack.parseAndAnalyze(src.first, src.second)) diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 6c673c311..89304ef3c 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -67,6 +67,7 @@ static string const g_strImportAst = "import-ast"; static string const g_strInputFile = "input-file"; static string const g_strYul = "yul"; static string const g_strYulDialect = "yul-dialect"; +static string const g_strDebugInfo = "debug-info"; static string const g_strIPFS = "ipfs"; static string const g_strLicense = "license"; static string const g_strLibraries = "libraries"; @@ -252,6 +253,7 @@ bool CommandLineOptions::operator==(CommandLineOptions const& _other) const noex output.evmVersion == _other.output.evmVersion && output.experimentalViaIR == _other.output.experimentalViaIR && output.revertStrings == _other.output.revertStrings && + output.debugInfoSelection == _other.output.debugInfoSelection && output.stopAfter == _other.output.stopAfter && input.mode == _other.input.mode && assembly.targetMachine == _other.assembly.targetMachine && @@ -595,6 +597,13 @@ General Information)").c_str(), po::value()->value_name(joinHumanReadable(g_revertStringsArgs, ",")), "Strip revert (and require) reason strings or add additional debugging information." ) + ( + g_strDebugInfo.c_str(), + po::value()->default_value(toString(DebugInfoSelection::Default())), + ("Debug info components to be included in the produced EVM assembly and Yul code. " + "Value can be all, none or a comma-separated list containing one or more of the " + "following components: " + joinHumanReadable(DebugInfoSelection::componentMap() | ranges::views::keys) + ".").c_str() + ) ( g_strStopAfter.c_str(), po::value()->value_name("stage"), @@ -935,6 +944,12 @@ bool CommandLineParser::processArgs() serr() << "Option --" << option << " is only valid in compiler and assembler modes." << endl; return false; } + + if (!m_args[g_strDebugInfo].defaulted()) + { + serr() << "Option --" << g_strDebugInfo << " is only valid in compiler and assembler modes." << endl; + return false; + } } if (m_args.count(g_strColor) > 0) @@ -961,6 +976,23 @@ bool CommandLineParser::processArgs() m_options.output.revertStrings = *revertStrings; } + if (!m_args[g_strDebugInfo].defaulted()) + { + string optionValue = m_args[g_strDebugInfo].as(); + m_options.output.debugInfoSelection = DebugInfoSelection::fromString(optionValue); + if (!m_options.output.debugInfoSelection.has_value()) + { + serr() << "Invalid value for --" << g_strDebugInfo << " option: " << optionValue << endl; + return false; + } + + if (m_options.output.debugInfoSelection->snippet && !m_options.output.debugInfoSelection->location) + { + serr() << "To use 'snippet' with --" << g_strDebugInfo << " you must select also 'location'." << endl; + return false; + } + } + if (!parseCombinedJsonOption()) return false; diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 1f09ea993..ad525ea3b 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -24,8 +24,12 @@ #include #include #include + #include + +#include #include + #include #include @@ -174,6 +178,7 @@ struct CommandLineOptions langutil::EVMVersion evmVersion; bool experimentalViaIR = false; RevertStrings revertStrings = RevertStrings::Default; + std::optional debugInfoSelection; CompilerStack::State stopAfter = CompilerStack::State::CompilationSuccessful; } output; diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/args b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/args new file mode 100644 index 000000000..77f60c746 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/args @@ -0,0 +1 @@ +--ir --ir-optimized --asm --optimize --debug-info all diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/input.sol b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/input.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output new file mode 100644 index 000000000..157594b2b --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output @@ -0,0 +1,213 @@ + +======= debug_info_in_yul_and_evm_asm_print_all/input.sol:C ======= +EVM assembly: + /* "debug_info_in_yul_and_evm_asm_print_all/input.sol":60:101 contract C {... */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + /* "debug_info_in_yul_and_evm_asm_print_all/input.sol":60:101 contract C {... */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + tag_2: + 0x00 + dup1 + revert + /* "debug_info_in_yul_and_evm_asm_print_all/input.sol":77:99 function f() public {} */ + tag_3: + stop + + auxdata: +} + +IR: +/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + + +/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_all/input.sol" +object "C_6" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + + return(_1, datasize("C_6_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 "contract C {..." + function constructor_C_6() { + + /// @src 0:60:101 "contract C {..." + + } + /// @src 0:60:101 "contract C {..." + + } + /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_all/input.sol" + object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + } + + default {} + } + if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @ast-id 5 + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + + } + /// @src 0:60:101 "contract C {..." + + } + + data ".metadata" hex"" + } + +} + + +Optimized IR: +/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + +/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_all/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + if callvalue() { revert(0, 0) } + let _1 := datasize("C_6_deployed") + codecopy(128, dataoffset("C_6_deployed"), _1) + return(128, _1) + } + } + /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_all/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + if iszero(lt(calldatasize(), 4)) + { + let _1 := 0 + if eq(0x26121ff0, shr(224, calldataload(_1))) + { + if callvalue() { revert(_1, _1) } + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + return(128, _1) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/args b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/args new file mode 100644 index 000000000..e0c752a3a --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/args @@ -0,0 +1 @@ +--ir --ir-optimized --asm --optimize --debug-info location,all,none diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/err b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/err new file mode 100644 index 000000000..99ed59cc0 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/err @@ -0,0 +1 @@ +Invalid value for --debug-info option: location,all,none diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/exit b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/input.sol b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all_and_none/input.sol new file mode 100644 index 000000000..e69de29bb diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/args b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/args new file mode 100644 index 000000000..6b47cc2c3 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/args @@ -0,0 +1 @@ +--ir --ir-optimized --asm --optimize --debug-info location diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/input.sol b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/input.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output new file mode 100644 index 000000000..505e734b9 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output @@ -0,0 +1,212 @@ + +======= debug_info_in_yul_and_evm_asm_print_location_only/input.sol:C ======= +EVM assembly: + /* "debug_info_in_yul_and_evm_asm_print_location_only/input.sol":60:101 */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + /* "debug_info_in_yul_and_evm_asm_print_location_only/input.sol":60:101 */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + tag_2: + 0x00 + dup1 + revert + /* "debug_info_in_yul_and_evm_asm_print_location_only/input.sol":77:99 */ + tag_3: + stop + + auxdata: +} + +IR: +/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + + +/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_location_only/input.sol" +object "C_6" { + code { + /// @src 0:60:101 + mstore(64, 128) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + + return(_1, datasize("C_6_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 + function constructor_C_6() { + + /// @src 0:60:101 + + } + /// @src 0:60:101 + + } + /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_location_only/input.sol" + object "C_6_deployed" { + code { + /// @src 0:60:101 + mstore(64, 128) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + } + + default {} + } + if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @src 0:77:99 + function fun_f_5() { + + } + /// @src 0:60:101 + + } + + data ".metadata" hex"" + } + +} + + +Optimized IR: +/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + +/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_location_only/input.sol" +object "C_6" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + if callvalue() { revert(0, 0) } + let _1 := datasize("C_6_deployed") + codecopy(128, dataoffset("C_6_deployed"), _1) + return(128, _1) + } + } + /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_location_only/input.sol" + object "C_6_deployed" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + if iszero(lt(calldatasize(), 4)) + { + let _1 := 0 + if eq(0x26121ff0, shr(224, calldataload(_1))) + { + if callvalue() { revert(_1, _1) } + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + return(128, _1) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/args b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/args new file mode 100644 index 000000000..89896f68a --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/args @@ -0,0 +1 @@ +--ir --ir-optimized --asm --optimize --debug-info none diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/input.sol b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/input.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output new file mode 100644 index 000000000..c8f76f990 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output @@ -0,0 +1,201 @@ + +======= debug_info_in_yul_and_evm_asm_print_none/input.sol:C ======= +EVM assembly: + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + tag_2: + 0x00 + dup1 + revert + tag_3: + stop + + auxdata: +} + +IR: +/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + + +/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_none/input.sol" +object "C_6" { + code { + + mstore(64, 128) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset("C_6_deployed"), datasize("C_6_deployed")) + + return(_1, datasize("C_6_deployed")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_6() { + + } + + } + /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_none/input.sol" + object "C_6_deployed" { + code { + + mstore(64, 128) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + } + + default {} + } + if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function fun_f_5() { + + } + + } + + data ".metadata" hex"" + } + +} + + +Optimized IR: +/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + +/// @use-src 0:"debug_info_in_yul_and_evm_asm_print_none/input.sol" +object "C_6" { + code { + { + mstore(64, 128) + if callvalue() { revert(0, 0) } + let _1 := datasize("C_6_deployed") + codecopy(128, dataoffset("C_6_deployed"), _1) + return(128, _1) + } + } + /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_none/input.sol" + object "C_6_deployed" { + code { + { + mstore(64, 128) + if iszero(lt(calldatasize(), 4)) + { + let _1 := 0 + if eq(0x26121ff0, shr(224, calldataload(_1))) + { + if callvalue() { revert(_1, _1) } + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + return(128, _1) + } + } + revert(0, 0) + } + } + data ".metadata" hex"" + } +} diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/args b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/args new file mode 100644 index 000000000..9f1e80de2 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/args @@ -0,0 +1 @@ +--ir --ir-optimized --asm --optimize --debug-info snippet diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/err b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/err new file mode 100644 index 000000000..4cd94075a --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/err @@ -0,0 +1 @@ +To use 'snippet' with --debug-info you must select also 'location'. diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/exit b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/input.sol b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/input.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_snippet_only/input.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/args b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/args new file mode 100644 index 000000000..24d48faf2 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/in.sol b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/in.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/input.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/input.json new file mode 100644 index 000000000..3059e1ecd --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_debug_info_in_yul_and_evm_asm_print_all/in.sol"]} + }, + "settings": { + "debug": {"debugInfo": ["*"]}, + "optimizer": {"enabled": true}, + "outputSelection": { + "*": {"*": ["ir", "irOptimized", "evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json new file mode 100644 index 000000000..4ef790de3 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json @@ -0,0 +1,230 @@ +{ + "contracts": + { + "C": + { + "C": + { + "evm": + { + "assembly": " /* \"C\":60:101 contract C {... */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + /* \"C\":60:101 contract C {... */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + tag_2: + 0x00 + dup1 + revert + /* \"C\":77:99 function f() public {} */ + tag_3: + stop + + auxdata: +} +" + }, + "ir": "/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + + +/// @use-src 0:\"C\" +object \"C_6\" { + code { + /// @src 0:60:101 \"contract C {...\" + mstore(64, 128) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"C_6_deployed\"), datasize(\"C_6_deployed\")) + + return(_1, datasize(\"C_6_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 \"contract C {...\" + function constructor_C_6() { + + /// @src 0:60:101 \"contract C {...\" + + } + /// @src 0:60:101 \"contract C {...\" + + } + /// @use-src 0:\"C\" + object \"C_6_deployed\" { + code { + /// @src 0:60:101 \"contract C {...\" + mstore(64, 128) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + } + + default {} + } + if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @ast-id 5 + /// @src 0:77:99 \"function f() public {}\" + function fun_f_5() { + + } + /// @src 0:60:101 \"contract C {...\" + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + +/// @use-src 0:\"C\" +object \"C_6\" { + code { + { + /// @src 0:60:101 \"contract C {...\" + mstore(64, 128) + if callvalue() { revert(0, 0) } + let _1 := datasize(\"C_6_deployed\") + codecopy(128, dataoffset(\"C_6_deployed\"), _1) + return(128, _1) + } + } + /// @use-src 0:\"C\" + object \"C_6_deployed\" { + code { + { + /// @src 0:60:101 \"contract C {...\" + mstore(64, 128) + if iszero(lt(calldatasize(), 4)) + { + let _1 := 0 + if eq(0x26121ff0, shr(224, calldataload(_1))) + { + if callvalue() { revert(_1, _1) } + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + return(128, _1) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "sources": + { + "C": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/args b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/args new file mode 100644 index 000000000..24d48faf2 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/in.sol b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/in.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/input.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/input.json new file mode 100644 index 000000000..8e338322b --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_debug_info_in_yul_and_evm_asm_print_location_only/in.sol"]} + }, + "settings": { + "debug": {"debugInfo": ["location"]}, + "optimizer": {"enabled": true}, + "outputSelection": { + "*": {"*": ["ir", "irOptimized", "evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json new file mode 100644 index 000000000..2aebdc0f2 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json @@ -0,0 +1,229 @@ +{ + "contracts": + { + "C": + { + "C": + { + "evm": + { + "assembly": " /* \"C\":60:101 */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + /* \"C\":60:101 */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + tag_2: + 0x00 + dup1 + revert + /* \"C\":77:99 */ + tag_3: + stop + + auxdata: +} +" + }, + "ir": "/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + + +/// @use-src 0:\"C\" +object \"C_6\" { + code { + /// @src 0:60:101 + mstore(64, 128) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"C_6_deployed\"), datasize(\"C_6_deployed\")) + + return(_1, datasize(\"C_6_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + /// @src 0:60:101 + function constructor_C_6() { + + /// @src 0:60:101 + + } + /// @src 0:60:101 + + } + /// @use-src 0:\"C\" + object \"C_6_deployed\" { + code { + /// @src 0:60:101 + mstore(64, 128) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + } + + default {} + } + if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + /// @src 0:77:99 + function fun_f_5() { + + } + /// @src 0:60:101 + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + +/// @use-src 0:\"C\" +object \"C_6\" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + if callvalue() { revert(0, 0) } + let _1 := datasize(\"C_6_deployed\") + codecopy(128, dataoffset(\"C_6_deployed\"), _1) + return(128, _1) + } + } + /// @use-src 0:\"C\" + object \"C_6_deployed\" { + code { + { + /// @src 0:60:101 + mstore(64, 128) + if iszero(lt(calldatasize(), 4)) + { + let _1 := 0 + if eq(0x26121ff0, shr(224, calldataload(_1))) + { + if callvalue() { revert(_1, _1) } + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + return(128, _1) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "sources": + { + "C": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/args b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/args new file mode 100644 index 000000000..24d48faf2 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/in.sol b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/in.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/input.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/input.json new file mode 100644 index 000000000..c9184d944 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_debug_info_in_yul_and_evm_asm_print_none/in.sol"]} + }, + "settings": { + "debug": {"debugInfo": []}, + "optimizer": {"enabled": true}, + "outputSelection": { + "*": {"*": ["ir", "irOptimized", "evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json new file mode 100644 index 000000000..be369ef1a --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json @@ -0,0 +1,218 @@ +{ + "contracts": + { + "C": + { + "C": + { + "evm": + { + "assembly": " mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert + tag_1: + pop + jumpi(tag_2, lt(calldatasize, 0x04)) + shr(0xe0, calldataload(0x00)) + dup1 + 0x26121ff0 + eq + tag_3 + jumpi + tag_2: + 0x00 + dup1 + revert + tag_3: + stop + + auxdata: +} +" + }, + "ir": "/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + + +/// @use-src 0:\"C\" +object \"C_6\" { + code { + + mstore(64, 128) + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + + constructor_C_6() + + let _1 := allocate_unbounded() + codecopy(_1, dataoffset(\"C_6_deployed\"), datasize(\"C_6_deployed\")) + + return(_1, datasize(\"C_6_deployed\")) + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function constructor_C_6() { + + } + + } + /// @use-src 0:\"C\" + object \"C_6_deployed\" { + code { + + mstore(64, 128) + + if iszero(lt(calldatasize(), 4)) + { + let selector := shift_right_224_unsigned(calldataload(0)) + switch selector + + case 0x26121ff0 + { + // f() + + if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } + abi_decode_tuple_(4, calldatasize()) + fun_f_5() + let memPos := allocate_unbounded() + let memEnd := abi_encode_tuple__to__fromStack(memPos ) + return(memPos, sub(memEnd, memPos)) + } + + default {} + } + if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() + + function shift_right_224_unsigned(value) -> newValue { + newValue := + + shr(224, value) + + } + + function allocate_unbounded() -> memPtr { + memPtr := mload(64) + } + + function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { + revert(0, 0) + } + + function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { + revert(0, 0) + } + + function abi_decode_tuple_(headStart, dataEnd) { + if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } + + } + + function abi_encode_tuple__to__fromStack(headStart ) -> tail { + tail := add(headStart, 0) + + } + + function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { + revert(0, 0) + } + + function fun_f_5() { + + } + + } + + data \".metadata\" hex\"\" + } + +} + +", + "irOptimized": "/*=====================================================* + * WARNING * + * Solidity to Yul compilation is still EXPERIMENTAL * + * It can result in LOSS OF FUNDS or worse * + * !USE AT YOUR OWN RISK! * + *=====================================================*/ + +/// @use-src 0:\"C\" +object \"C_6\" { + code { + { + mstore(64, 128) + if callvalue() { revert(0, 0) } + let _1 := datasize(\"C_6_deployed\") + codecopy(128, dataoffset(\"C_6_deployed\"), _1) + return(128, _1) + } + } + /// @use-src 0:\"C\" + object \"C_6_deployed\" { + code { + { + mstore(64, 128) + if iszero(lt(calldatasize(), 4)) + { + let _1 := 0 + if eq(0x26121ff0, shr(224, calldataload(_1))) + { + if callvalue() { revert(_1, _1) } + if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) } + return(128, _1) + } + } + revert(0, 0) + } + } + data \".metadata\" hex\"\" + } +} +" + } + } + }, + "sources": + { + "C": + { + "id": 0 + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/args b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/args new file mode 100644 index 000000000..24d48faf2 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/in.sol b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/in.sol new file mode 100644 index 000000000..415509ef9 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/in.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +pragma solidity >=0.0; + +contract C { + function f() public {} +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/input.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/input.json new file mode 100644 index 000000000..962688913 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/input.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "C": {"urls": ["standard_debug_info_in_yul_and_evm_asm_print_snippet_only/in.sol"]} + }, + "settings": { + "debug": {"debugInfo": ["snippet"]}, + "optimizer": {"enabled": true}, + "outputSelection": { + "*": {"*": ["ir", "irOptimized", "evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/output.json new file mode 100644 index 000000000..fb7f199a7 --- /dev/null +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_snippet_only/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "To use 'snippet' with settings.debug.debugInfo you must select also 'location'.", + "message": "To use 'snippet' with settings.debug.debugInfo you must select also 'location'.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_all/args b/test/cmdlineTests/standard_yul_debug_info_print_all/args new file mode 100644 index 000000000..24d48faf2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_all/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/standard_yul_debug_info_print_all/in.yul b/test/cmdlineTests/standard_yul_debug_info_print_all/in.yul new file mode 100644 index 000000000..6d1ebe21b --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_all/in.yul @@ -0,0 +1,15 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_all/input.json b/test/cmdlineTests/standard_yul_debug_info_print_all/input.json new file mode 100644 index 000000000..1e6ed81a4 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_all/input.json @@ -0,0 +1,12 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_debug_info_print_all/in.yul"]} + }, + "settings": { + "debug": {"debugInfo": ["*"]}, + "outputSelection": { + "*": {"*": ["evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_all/output.json b/test/cmdlineTests/standard_yul_debug_info_print_all/output.json new file mode 100644 index 000000000..b57bc9188 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_all/output.json @@ -0,0 +1,36 @@ +{ + "contracts": + { + "C": + { + "C_6_deployed": + { + "evm": + { + "assembly": " /* \"input.sol\":60:101 */ + mstore(0x40, 0x80) + tag_2 + tag_1 + jump\t// in +tag_2: + /* \"input.sol\":77:99 */ + jump(tag_3) +tag_1: + jump\t// out +tag_3: +" + } + } + } + }, + "errors": + [ + { + "component": "general", + "formattedMessage": "Yul is still experimental. Please use the output with care.", + "message": "Yul is still experimental. Please use the output with care.", + "severity": "warning", + "type": "Warning" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_location_only/args b/test/cmdlineTests/standard_yul_debug_info_print_location_only/args new file mode 100644 index 000000000..24d48faf2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_location_only/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/standard_yul_debug_info_print_location_only/in.yul b/test/cmdlineTests/standard_yul_debug_info_print_location_only/in.yul new file mode 100644 index 000000000..6d1ebe21b --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_location_only/in.yul @@ -0,0 +1,15 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_location_only/input.json b/test/cmdlineTests/standard_yul_debug_info_print_location_only/input.json new file mode 100644 index 000000000..867bc6e70 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_location_only/input.json @@ -0,0 +1,12 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_debug_info_print_location_only/in.yul"]} + }, + "settings": { + "debug": {"debugInfo": ["location"]}, + "outputSelection": { + "*": {"*": ["evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_location_only/output.json b/test/cmdlineTests/standard_yul_debug_info_print_location_only/output.json new file mode 100644 index 000000000..0ce9fd2de --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_location_only/output.json @@ -0,0 +1,36 @@ +{ + "contracts": + { + "C": + { + "C_6_deployed": + { + "evm": + { + "assembly": " /* \"input.sol\":60:101 */ + mstore(0x40, 0x80) + tag_2 + tag_1 + jump\t// in +tag_2: + /* \"input.sol\":77:99 */ + jump(tag_3) +tag_1: + jump\t// out +tag_3: +" + } + } + } + }, + "errors": + [ + { + "component": "general", + "formattedMessage": "Yul is still experimental. Please use the output with care.", + "message": "Yul is still experimental. Please use the output with care.", + "severity": "warning", + "type": "Warning" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_none/args b/test/cmdlineTests/standard_yul_debug_info_print_none/args new file mode 100644 index 000000000..24d48faf2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_none/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/standard_yul_debug_info_print_none/in.yul b/test/cmdlineTests/standard_yul_debug_info_print_none/in.yul new file mode 100644 index 000000000..6d1ebe21b --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_none/in.yul @@ -0,0 +1,15 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_none/input.json b/test/cmdlineTests/standard_yul_debug_info_print_none/input.json new file mode 100644 index 000000000..705cf3879 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_none/input.json @@ -0,0 +1,12 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_debug_info_print_none/in.yul"]} + }, + "settings": { + "debug": {"debugInfo": []}, + "outputSelection": { + "*": {"*": ["evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_none/output.json b/test/cmdlineTests/standard_yul_debug_info_print_none/output.json new file mode 100644 index 000000000..8203ee0a2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_none/output.json @@ -0,0 +1,34 @@ +{ + "contracts": + { + "C": + { + "C_6_deployed": + { + "evm": + { + "assembly": " mstore(0x40, 0x80) + tag_2 + tag_1 + jump\t// in +tag_2: + jump(tag_3) +tag_1: + jump\t// out +tag_3: +" + } + } + } + }, + "errors": + [ + { + "component": "general", + "formattedMessage": "Yul is still experimental. Please use the output with care.", + "message": "Yul is still experimental. Please use the output with care.", + "severity": "warning", + "type": "Warning" + } + ] +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/args b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/args new file mode 100644 index 000000000..24d48faf2 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 --allow-paths . diff --git a/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/in.yul b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/in.yul new file mode 100644 index 000000000..6d1ebe21b --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/in.yul @@ -0,0 +1,15 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/input.json b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/input.json new file mode 100644 index 000000000..ee247218f --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/input.json @@ -0,0 +1,12 @@ +{ + "language": "Yul", + "sources": { + "C": {"urls": ["standard_yul_debug_info_print_snippet_only/in.yul"]} + }, + "settings": { + "debug": {"debugInfo": ["snippet"]}, + "outputSelection": { + "*": {"*": ["evm.assembly"]} + } + } +} diff --git a/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/output.json b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/output.json new file mode 100644 index 000000000..fb7f199a7 --- /dev/null +++ b/test/cmdlineTests/standard_yul_debug_info_print_snippet_only/output.json @@ -0,0 +1,12 @@ +{ + "errors": + [ + { + "component": "general", + "formattedMessage": "To use 'snippet' with settings.debug.debugInfo you must select also 'location'.", + "message": "To use 'snippet' with settings.debug.debugInfo you must select also 'location'.", + "severity": "error", + "type": "JSONError" + } + ] +} diff --git a/test/cmdlineTests/strict_asm_debug_info_print_all/args b/test/cmdlineTests/strict_asm_debug_info_print_all/args new file mode 100644 index 000000000..cfe8a15a2 --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_all/args @@ -0,0 +1 @@ +--strict-assembly --debug-info all diff --git a/test/cmdlineTests/strict_asm_debug_info_print_all/err b/test/cmdlineTests/strict_asm_debug_info_print_all/err new file mode 100644 index 000000000..014a1178f --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_all/err @@ -0,0 +1 @@ +Warning: Yul is still experimental. Please use the output with care. diff --git a/test/cmdlineTests/strict_asm_debug_info_print_all/input.yul b/test/cmdlineTests/strict_asm_debug_info_print_all/input.yul new file mode 100644 index 000000000..6d1ebe21b --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_all/input.yul @@ -0,0 +1,15 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/strict_asm_debug_info_print_all/output b/test/cmdlineTests/strict_asm_debug_info_print_all/output new file mode 100644 index 000000000..e83614b62 --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_all/output @@ -0,0 +1,32 @@ + +======= strict_asm_debug_info_print_all/input.yul (EVM) ======= + +Pretty printed source: +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { } + } +} + + +Binary representation: +6080604052600a600e565b6010565b565b + +Text representation: + /* "input.sol":60:101 */ + mstore(0x40, 0x80) + tag_2 + tag_1 + jump // in +tag_2: + /* "input.sol":77:99 */ + jump(tag_3) +tag_1: + jump // out +tag_3: diff --git a/test/cmdlineTests/strict_asm_debug_info_print_location_only/args b/test/cmdlineTests/strict_asm_debug_info_print_location_only/args new file mode 100644 index 000000000..0d6ad325b --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_location_only/args @@ -0,0 +1 @@ +--strict-assembly --debug-info location diff --git a/test/cmdlineTests/strict_asm_debug_info_print_location_only/err b/test/cmdlineTests/strict_asm_debug_info_print_location_only/err new file mode 100644 index 000000000..014a1178f --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_location_only/err @@ -0,0 +1 @@ +Warning: Yul is still experimental. Please use the output with care. diff --git a/test/cmdlineTests/strict_asm_debug_info_print_location_only/input.yul b/test/cmdlineTests/strict_asm_debug_info_print_location_only/input.yul new file mode 100644 index 000000000..6d1ebe21b --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_location_only/input.yul @@ -0,0 +1,15 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/strict_asm_debug_info_print_location_only/output b/test/cmdlineTests/strict_asm_debug_info_print_location_only/output new file mode 100644 index 000000000..a4fd0e494 --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_location_only/output @@ -0,0 +1,32 @@ + +======= strict_asm_debug_info_print_location_only/input.yul (EVM) ======= + +Pretty printed source: +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 + mstore(64, 128) + fun_f_5() + /// @src 0:77:99 + function fun_f_5() + { } + } +} + + +Binary representation: +6080604052600a600e565b6010565b565b + +Text representation: + /* "input.sol":60:101 */ + mstore(0x40, 0x80) + tag_2 + tag_1 + jump // in +tag_2: + /* "input.sol":77:99 */ + jump(tag_3) +tag_1: + jump // out +tag_3: diff --git a/test/cmdlineTests/strict_asm_debug_info_print_none/args b/test/cmdlineTests/strict_asm_debug_info_print_none/args new file mode 100644 index 000000000..7e891dd86 --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_none/args @@ -0,0 +1 @@ +--strict-assembly --debug-info none diff --git a/test/cmdlineTests/strict_asm_debug_info_print_none/err b/test/cmdlineTests/strict_asm_debug_info_print_none/err new file mode 100644 index 000000000..014a1178f --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_none/err @@ -0,0 +1 @@ +Warning: Yul is still experimental. Please use the output with care. diff --git a/test/cmdlineTests/strict_asm_debug_info_print_none/input.yul b/test/cmdlineTests/strict_asm_debug_info_print_none/input.yul new file mode 100644 index 000000000..6d1ebe21b --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_none/input.yul @@ -0,0 +1,15 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/cmdlineTests/strict_asm_debug_info_print_none/output b/test/cmdlineTests/strict_asm_debug_info_print_none/output new file mode 100644 index 000000000..fc8841c9a --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_none/output @@ -0,0 +1,28 @@ + +======= strict_asm_debug_info_print_none/input.yul (EVM) ======= + +Pretty printed source: +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + mstore(64, 128) + fun_f_5() + function fun_f_5() + { } + } +} + + +Binary representation: +6080604052600a600e565b6010565b565b + +Text representation: + mstore(0x40, 0x80) + tag_2 + tag_1 + jump // in +tag_2: + jump(tag_3) +tag_1: + jump // out +tag_3: diff --git a/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/args b/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/args new file mode 100644 index 000000000..362fd6515 --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/args @@ -0,0 +1 @@ +--strict-assembly --debug-info snippet diff --git a/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/err b/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/err new file mode 100644 index 000000000..4cd94075a --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/err @@ -0,0 +1 @@ +To use 'snippet' with --debug-info you must select also 'location'. diff --git a/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/exit b/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/exit new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/input.yul b/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/input.yul new file mode 100644 index 000000000..6d1ebe21b --- /dev/null +++ b/test/cmdlineTests/strict_asm_debug_info_print_snippet_only/input.yul @@ -0,0 +1,15 @@ +/// @use-src 0:"input.sol" +object "C_6_deployed" { + code { + /// @src 0:60:101 "contract C {..." + mstore(64, 128) + + // f() + fun_f_5() + + /// @src 0:77:99 "function f() public {}" + function fun_f_5() { + } + /// @src 0:60:101 "contract C {..." + } +} diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 939850304..f2e4ea387 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -127,6 +127,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) "--evm-version=spuriousDragon", "--experimental-via-ir", "--revert-strings=strip", + "--debug-info=location", "--pretty-json", "--json-indent=7", "--no-color", @@ -180,6 +181,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) expectedOptions.output.evmVersion = EVMVersion::spuriousDragon(); expectedOptions.output.experimentalViaIR = true; expectedOptions.output.revertStrings = RevertStrings::Strip; + expectedOptions.output.debugInfoSelection = DebugInfoSelection::fromString("location"); expectedOptions.formatting.json = JsonFormat{JsonFormat::Pretty, 7}; expectedOptions.linker.libraries = { {"dir1/file1.sol:L", h160("1234567890123456789012345678901234567890")}, @@ -269,6 +271,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) "--overwrite", "--evm-version=spuriousDragon", "--revert-strings=strip", // Accepted but has no effect in assembly mode + "--debug-info=location", "--pretty-json", "--json-indent=1", "--no-color", @@ -315,6 +318,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) expectedOptions.output.overwriteFiles = true; expectedOptions.output.evmVersion = EVMVersion::spuriousDragon(); expectedOptions.output.revertStrings = RevertStrings::Strip; + expectedOptions.output.debugInfoSelection = DebugInfoSelection::fromString("location"); expectedOptions.formatting.json = JsonFormat {JsonFormat::Pretty, 1}; expectedOptions.assembly.targetMachine = expectedMachine; expectedOptions.assembly.inputLanguage = expectedLanguage; From ee1455ce95005cf3732e96033d9055cfd17ecd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 8 Oct 2021 14:44:43 +0200 Subject: [PATCH 30/62] Define solThrow() macro to make throwing simple errors less verbose --- libsolutil/Assertions.h | 11 +++-------- libsolutil/Exceptions.h | 13 +++++++++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/libsolutil/Assertions.h b/libsolutil/Assertions.h index f04e90a1f..81823e040 100644 --- a/libsolutil/Assertions.h +++ b/libsolutil/Assertions.h @@ -61,14 +61,9 @@ inline std::string stringOrDefault(std::string _string, std::string _defaultStri do \ { \ if (!(_condition)) \ - ::boost::throw_exception( \ - _exceptionType() << \ - ::solidity::util::errinfo_comment( \ - ::solidity::util::assertions::stringOrDefault(_description, _defaultDescription) \ - ) << \ - ::boost::throw_function(ETH_FUNC) << \ - ::boost::throw_file(__FILE__) << \ - ::boost::throw_line(__LINE__) \ + solThrow( \ + _exceptionType, \ + ::solidity::util::assertions::stringOrDefault(_description, _defaultDescription) \ ); \ } \ while (false) diff --git a/libsolutil/Exceptions.h b/libsolutil/Exceptions.h index 379221ab2..d83d8004b 100644 --- a/libsolutil/Exceptions.h +++ b/libsolutil/Exceptions.h @@ -43,6 +43,19 @@ struct Exception: virtual std::exception, virtual boost::exception private: }; +/// Throws an exception with a given description and extra information about the location the +/// exception was thrown from. +/// @param _exceptionType The type of the exception to throw (not an instance). +/// @param _description The message that describes the error. +#define solThrow(_exceptionType, _description) \ + ::boost::throw_exception( \ + _exceptionType() << \ + ::solidity::util::errinfo_comment(_description) << \ + ::boost::throw_function(ETH_FUNC) << \ + ::boost::throw_file(__FILE__) << \ + ::boost::throw_line(__LINE__) \ + ) + #define DEV_SIMPLE_EXCEPTION(X) struct X: virtual ::solidity::util::Exception { const char* what() const noexcept override { return #X; } } DEV_SIMPLE_EXCEPTION(InvalidAddress); From e136788493ed0d108579eb77a65500c90aed3cf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 11 Oct 2021 18:34:47 +0200 Subject: [PATCH 31/62] Replace BOOST_THROW_EXCEPTION() with solThrow() where appropriate --- libsolidity/interface/CompilerStack.cpp | 110 ++++++++++++------------ libsolidity/interface/FileReader.cpp | 5 +- 2 files changed, 56 insertions(+), 59 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index e49c15387..47c86e67e 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -201,7 +201,7 @@ void CompilerStack::findAndReportCyclicContractDependencies() void CompilerStack::setRemappings(vector _remappings) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set remappings before parsing.")); + solThrow(CompilerError, "Must set remappings before parsing."); for (auto const& remapping: _remappings) solAssert(!remapping.prefix.empty(), ""); m_importRemapper.setRemappings(move(_remappings)); @@ -210,28 +210,28 @@ void CompilerStack::setRemappings(vector _remappings) void CompilerStack::setViaIR(bool _viaIR) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set viaIR before parsing.")); + solThrow(CompilerError, "Must set viaIR before parsing."); m_viaIR = _viaIR; } void CompilerStack::setEVMVersion(langutil::EVMVersion _version) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set EVM version before parsing.")); + solThrow(CompilerError, "Must set EVM version before parsing."); m_evmVersion = _version; } void CompilerStack::setModelCheckerSettings(ModelCheckerSettings _settings) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set model checking settings before parsing.")); + solThrow(CompilerError, "Must set model checking settings before parsing."); m_modelCheckerSettings = _settings; } void CompilerStack::setLibraries(std::map const& _libraries) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set libraries before parsing.")); + solThrow(CompilerError, "Must set libraries before parsing."); m_libraries = _libraries; } @@ -245,14 +245,14 @@ void CompilerStack::setOptimiserSettings(bool _optimize, size_t _runs) void CompilerStack::setOptimiserSettings(OptimiserSettings _settings) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set optimiser settings before parsing.")); + solThrow(CompilerError, "Must set optimiser settings before parsing."); m_optimiserSettings = std::move(_settings); } void CompilerStack::setRevertStringBehaviour(RevertStrings _revertStrings) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set revert string settings before parsing.")); + solThrow(CompilerError, "Must set revert string settings before parsing."); solUnimplementedAssert(_revertStrings != RevertStrings::VerboseDebug); m_revertStrings = _revertStrings; } @@ -260,21 +260,21 @@ void CompilerStack::setRevertStringBehaviour(RevertStrings _revertStrings) void CompilerStack::useMetadataLiteralSources(bool _metadataLiteralSources) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set use literal sources before parsing.")); + solThrow(CompilerError, "Must set use literal sources before parsing."); m_metadataLiteralSources = _metadataLiteralSources; } void CompilerStack::setMetadataHash(MetadataHash _metadataHash) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set metadata hash before parsing.")); + solThrow(CompilerError, "Must set metadata hash before parsing."); m_metadataHash = _metadataHash; } void CompilerStack::addSMTLib2Response(h256 const& _hash, string const& _response) { if (m_stackState >= ParsedAndImported) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must add SMTLib2 responses before parsing.")); + solThrow(CompilerError, "Must add SMTLib2 responses before parsing."); m_smtlib2Responses[_hash] = _response; } @@ -310,9 +310,9 @@ void CompilerStack::reset(bool _keepSettings) void CompilerStack::setSources(StringMap _sources) { if (m_stackState == SourcesSet) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Cannot change sources once set.")); + solThrow(CompilerError, "Cannot change sources once set."); if (m_stackState != Empty) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set sources before parsing.")); + solThrow(CompilerError, "Must set sources before parsing."); for (auto source: _sources) m_sources[source.first].charStream = make_unique(/*content*/std::move(source.second), /*name*/source.first); m_stackState = SourcesSet; @@ -321,7 +321,7 @@ void CompilerStack::setSources(StringMap _sources) bool CompilerStack::parse() { if (m_stackState != SourcesSet) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must call parse only after the SourcesSet state.")); + solThrow(CompilerError, "Must call parse only after the SourcesSet state."); m_errorReporter.clear(); if (SemVerVersion{string(VersionString)}.isPrerelease()) @@ -369,7 +369,7 @@ bool CompilerStack::parse() void CompilerStack::importASTs(map const& _sources) { if (m_stackState != Empty) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must call importASTs only before the SourcesSet state.")); + solThrow(CompilerError, "Must call importASTs only before the SourcesSet state."); m_sourceJsons = _sources; map> reconstructedSources = ASTJsonImporter(m_evmVersion).jsonToSourceUnit(m_sourceJsons); for (auto& src: reconstructedSources) @@ -392,7 +392,7 @@ void CompilerStack::importASTs(map const& _sources) bool CompilerStack::analyze() { if (m_stackState != ParsedAndImported || m_stackState >= AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must call analyze only after parsing was performed.")); + solThrow(CompilerError, "Must call analyze only after parsing was performed."); resolveImports(); for (Source const* source: m_sourceOrder) @@ -619,7 +619,7 @@ bool CompilerStack::compile(State _stopAfter) return true; if (m_hasError) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Called compile with errors.")); + solThrow(CompilerError, "Called compile with errors."); // Only compile contracts individually which have been requested. map> otherCompilers; @@ -691,7 +691,7 @@ void CompilerStack::link() vector CompilerStack::contractNames() const { if (m_stackState < Parsed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); + solThrow(CompilerError, "Parsing was not successful."); vector contractNames; for (auto const& contract: m_contracts) contractNames.push_back(contract.first); @@ -701,7 +701,7 @@ vector CompilerStack::contractNames() const string const CompilerStack::lastContractName(optional const& _sourceName) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); + solThrow(CompilerError, "Parsing was not successful."); // try to find some user-supplied contract string contractName; for (auto const& it: m_sources) @@ -714,7 +714,7 @@ string const CompilerStack::lastContractName(optional const& _sourceName evmasm::AssemblyItems const* CompilerStack::assemblyItems(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); Contract const& currentContract = contract(_contractName); return currentContract.evmAssembly ? ¤tContract.evmAssembly->items() : nullptr; @@ -723,7 +723,7 @@ evmasm::AssemblyItems const* CompilerStack::assemblyItems(string const& _contrac evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); Contract const& currentContract = contract(_contractName); return currentContract.evmRuntimeAssembly ? ¤tContract.evmRuntimeAssembly->items() : nullptr; @@ -732,7 +732,7 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _ Json::Value CompilerStack::generatedSources(string const& _contractName, bool _runtime) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); Contract const& c = contract(_contractName); util::LazyInit const& sources = @@ -775,7 +775,7 @@ Json::Value CompilerStack::generatedSources(string const& _contractName, bool _r string const* CompilerStack::sourceMapping(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); Contract const& c = contract(_contractName); if (!c.sourceMapping) @@ -789,7 +789,7 @@ string const* CompilerStack::sourceMapping(string const& _contractName) const string const* CompilerStack::runtimeSourceMapping(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); Contract const& c = contract(_contractName); if (!c.runtimeSourceMapping) @@ -805,7 +805,7 @@ string const* CompilerStack::runtimeSourceMapping(string const& _contractName) c std::string const CompilerStack::filesystemFriendlyName(string const& _contractName) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); + solThrow(CompilerError, "No compiled contracts found."); // Look up the contract (by its fully-qualified name) Contract const& matchContract = m_contracts.at(_contractName); @@ -829,7 +829,7 @@ std::string const CompilerStack::filesystemFriendlyName(string const& _contractN string const& CompilerStack::yulIR(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); return contract(_contractName).yulIR; } @@ -837,7 +837,7 @@ string const& CompilerStack::yulIR(string const& _contractName) const string const& CompilerStack::yulIROptimized(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); return contract(_contractName).yulIROptimized; } @@ -845,7 +845,7 @@ string const& CompilerStack::yulIROptimized(string const& _contractName) const string const& CompilerStack::ewasm(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); return contract(_contractName).ewasm; } @@ -853,7 +853,7 @@ string const& CompilerStack::ewasm(string const& _contractName) const evmasm::LinkerObject const& CompilerStack::ewasmObject(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); return contract(_contractName).ewasmObject; } @@ -861,7 +861,7 @@ evmasm::LinkerObject const& CompilerStack::ewasmObject(string const& _contractNa evmasm::LinkerObject const& CompilerStack::object(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); return contract(_contractName).object; } @@ -869,7 +869,7 @@ evmasm::LinkerObject const& CompilerStack::object(string const& _contractName) c evmasm::LinkerObject const& CompilerStack::runtimeObject(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); return contract(_contractName).runtimeObject; } @@ -878,7 +878,7 @@ evmasm::LinkerObject const& CompilerStack::runtimeObject(string const& _contract string CompilerStack::assemblyString(string const& _contractName, StringMap const& _sourceCodes) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); Contract const& currentContract = contract(_contractName); if (currentContract.evmAssembly) @@ -891,7 +891,7 @@ string CompilerStack::assemblyString(string const& _contractName, StringMap cons Json::Value CompilerStack::assemblyJSON(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); Contract const& currentContract = contract(_contractName); if (currentContract.evmAssembly) @@ -922,7 +922,7 @@ map CompilerStack::sourceIndices() const Json::Value const& CompilerStack::contractABI(string const& _contractName) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); return contractABI(contract(_contractName)); } @@ -930,7 +930,7 @@ Json::Value const& CompilerStack::contractABI(string const& _contractName) const Json::Value const& CompilerStack::contractABI(Contract const& _contract) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); solAssert(_contract.contract, ""); @@ -940,7 +940,7 @@ Json::Value const& CompilerStack::contractABI(Contract const& _contract) const Json::Value const& CompilerStack::storageLayout(string const& _contractName) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); return storageLayout(contract(_contractName)); } @@ -948,7 +948,7 @@ Json::Value const& CompilerStack::storageLayout(string const& _contractName) con Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); solAssert(_contract.contract, ""); @@ -958,7 +958,7 @@ Json::Value const& CompilerStack::storageLayout(Contract const& _contract) const Json::Value const& CompilerStack::natspecUser(string const& _contractName) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); return natspecUser(contract(_contractName)); } @@ -966,7 +966,7 @@ Json::Value const& CompilerStack::natspecUser(string const& _contractName) const Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); solAssert(_contract.contract, ""); @@ -976,7 +976,7 @@ Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const Json::Value const& CompilerStack::natspecDev(string const& _contractName) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); return natspecDev(contract(_contractName)); } @@ -984,7 +984,7 @@ Json::Value const& CompilerStack::natspecDev(string const& _contractName) const Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); solAssert(_contract.contract, ""); @@ -994,7 +994,7 @@ Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const Json::Value CompilerStack::methodIdentifiers(string const& _contractName) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); Json::Value methodIdentifiers(Json::objectValue); for (auto const& it: contractDefinition(_contractName).interfaceFunctions()) @@ -1005,7 +1005,7 @@ Json::Value CompilerStack::methodIdentifiers(string const& _contractName) const bytes CompilerStack::cborMetadata(string const& _contractName, bool _forIR) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); return createCBORMetadata(contract(_contractName), _forIR); } @@ -1013,7 +1013,7 @@ bytes CompilerStack::cborMetadata(string const& _contractName, bool _forIR) cons string const& CompilerStack::metadata(Contract const& _contract) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); solAssert(_contract.contract, ""); @@ -1023,7 +1023,7 @@ string const& CompilerStack::metadata(Contract const& _contract) const CharStream const& CompilerStack::charStream(string const& _sourceName) const { if (m_stackState < SourcesSet) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No sources set.")); + solThrow(CompilerError, "No sources set."); solAssert(source(_sourceName).charStream, ""); @@ -1033,9 +1033,9 @@ CharStream const& CompilerStack::charStream(string const& _sourceName) const SourceUnit const& CompilerStack::ast(string const& _sourceName) const { if (m_stackState < Parsed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing not yet performed.")); + solThrow(CompilerError, "Parsing not yet performed."); if (!source(_sourceName).ast && !m_parserErrorRecovery) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); + solThrow(CompilerError, "Parsing was not successful."); return *source(_sourceName).ast; } @@ -1043,7 +1043,7 @@ SourceUnit const& CompilerStack::ast(string const& _sourceName) const ContractDefinition const& CompilerStack::contractDefinition(string const& _contractName) const { if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Analysis was not successful.")); + solThrow(CompilerError, "Analysis was not successful."); return *contract(_contractName).contract; } @@ -1054,7 +1054,7 @@ size_t CompilerStack::functionEntryPoint( ) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); for (auto&& [name, data]: contract(_contractName).runtimeObject.functionDebugData) if (data.sourceID == _function.id()) @@ -1256,7 +1256,7 @@ void CompilerStack::compileContract( solAssert(!m_viaIR, ""); solAssert(m_stackState >= AnalysisPerformed, ""); if (m_hasError) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Called compile with errors.")); + solThrow(CompilerError, "Called compile with errors."); if (_otherCompilers.count(&_contract)) return; @@ -1294,7 +1294,7 @@ void CompilerStack::generateIR(ContractDefinition const& _contract) { solAssert(m_stackState >= AnalysisPerformed, ""); if (m_hasError) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Called generateIR with errors.")); + solThrow(CompilerError, "Called generateIR with errors."); Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName()); if (!compiledContract.yulIR.empty()) @@ -1331,7 +1331,7 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract) { solAssert(m_stackState >= AnalysisPerformed, ""); if (m_hasError) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Called generateEVMFromIR with errors.")); + solThrow(CompilerError, "Called generateEVMFromIR with errors."); if (!_contract.canBeDeployed()) return; @@ -1358,7 +1358,7 @@ void CompilerStack::generateEwasm(ContractDefinition const& _contract) { solAssert(m_stackState >= AnalysisPerformed, ""); if (m_hasError) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Called generateEwasm with errors.")); + solThrow(CompilerError, "Called generateEwasm with errors."); if (!_contract.canBeDeployed()) return; @@ -1412,14 +1412,14 @@ CompilerStack::Contract const& CompilerStack::contract(string const& _contractNa } // If we get here, both lookup methods failed. - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Contract \"" + _contractName + "\" not found.")); + solThrow(CompilerError, "Contract \"" + _contractName + "\" not found."); } CompilerStack::Source const& CompilerStack::source(string const& _sourceName) const { auto it = m_sources.find(_sourceName); if (it == m_sources.end()) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Given source file not found.")); + solThrow(CompilerError, "Given source file not found."); return it->second; } @@ -1658,7 +1658,7 @@ Json::Value gasToJson(GasEstimator::GasConsumption const& _gas) Json::Value CompilerStack::gasEstimates(string const& _contractName) const { if (m_stackState != CompilationSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); + solThrow(CompilerError, "Compilation was not successful."); if (!assemblyItems(_contractName) && !runtimeAssemblyItems(_contractName)) return Json::Value(); diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index 6bf5db75c..cfd1feb33 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -104,10 +104,7 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so try { if (_kind != ReadCallback::kindString(ReadCallback::Kind::ReadFile)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment( - "ReadFile callback used as callback kind " + - _kind - )); + solAssert(false, "ReadFile callback used as callback kind " + _kind); string strippedSourceUnitName = _sourceUnitName; if (strippedSourceUnitName.find("file://") == 0) strippedSourceUnitName.erase(0, 7); From 591ba184e902386aeed3cc44792a59f479a4a7f2 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Tue, 12 Oct 2021 15:13:35 +0200 Subject: [PATCH 32/62] Adds some more version pragma test cases. --- test/libsolidity/SemVerMatcher.cpp | 2 ++ test/libsolidity/syntaxTests/pragma/broken_version_6.sol | 3 +++ test/libsolidity/syntaxTests/pragma/broken_version_7.sol | 3 +++ test/libsolidity/syntaxTests/pragma/version_range.sol | 2 ++ 4 files changed, 10 insertions(+) create mode 100644 test/libsolidity/syntaxTests/pragma/broken_version_6.sol create mode 100644 test/libsolidity/syntaxTests/pragma/broken_version_7.sol create mode 100644 test/libsolidity/syntaxTests/pragma/version_range.sol diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index b0fbb8547..a69b2a39d 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -171,6 +171,8 @@ BOOST_AUTO_TEST_CASE(negative_range) { // Negative range tests vector> tests = { + {"^0^1", "0.0.0"}, + {"^0^1", "1.0.0"}, {"1.0.0 - 2.0.0", "2.2.3"}, {"1.0", "1.0.0-pre"}, {"1", "1.0.0-pre"}, diff --git a/test/libsolidity/syntaxTests/pragma/broken_version_6.sol b/test/libsolidity/syntaxTests/pragma/broken_version_6.sol new file mode 100644 index 000000000..ab98e4f2a --- /dev/null +++ b/test/libsolidity/syntaxTests/pragma/broken_version_6.sol @@ -0,0 +1,3 @@ +pragma solidity v1.2.3; +// ---- +// ParserError 1684: (0-23): Found version pragma, but failed to parse it. Please ensure there is a trailing semicolon. diff --git a/test/libsolidity/syntaxTests/pragma/broken_version_7.sol b/test/libsolidity/syntaxTests/pragma/broken_version_7.sol new file mode 100644 index 000000000..b4b6fea7a --- /dev/null +++ b/test/libsolidity/syntaxTests/pragma/broken_version_7.sol @@ -0,0 +1,3 @@ +pragma solidity >0.5.0<; +// ---- +// ParserError 1684: (0-24): Found version pragma, but failed to parse it. Please ensure there is a trailing semicolon. diff --git a/test/libsolidity/syntaxTests/pragma/version_range.sol b/test/libsolidity/syntaxTests/pragma/version_range.sol new file mode 100644 index 000000000..4d6cdf6b9 --- /dev/null +++ b/test/libsolidity/syntaxTests/pragma/version_range.sol @@ -0,0 +1,2 @@ +pragma solidity >=0.4.0 <0.9.0; +// ---- From 76f31e2c4e9cda441a0edcdb85cd2a564d8c8573 Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Tue, 12 Oct 2021 15:24:55 +0200 Subject: [PATCH 33/62] Whiskers: Support conditional value parameters for lists --- libsolutil/Whiskers.cpp | 12 +++++++----- libsolutil/Whiskers.h | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/libsolutil/Whiskers.cpp b/libsolutil/Whiskers.cpp index e236104c7..340527bdd 100644 --- a/libsolutil/Whiskers.cpp +++ b/libsolutil/Whiskers.cpp @@ -189,11 +189,13 @@ string Whiskers::replace( if (conditionName[0] == '+') { string tag = conditionName.substr(1); - assertThrow( - _parameters.count(tag), - WhiskersError, "Tag " + tag + " used as condition but was not set." - ); - conditionValue = !_parameters.at(tag).empty(); + + if (_parameters.count(tag)) + conditionValue = !_parameters.at(tag).empty(); + else if (_listParameters.count(tag)) + conditionValue = !_listParameters.at(tag).empty(); + else + assertThrow(false, WhiskersError, "Tag " + tag + " used as condition but was not set."); } else { diff --git a/libsolutil/Whiskers.h b/libsolutil/Whiskers.h index 113fbe6ed..7bbf74f09 100644 --- a/libsolutil/Whiskers.h +++ b/libsolutil/Whiskers.h @@ -60,12 +60,13 @@ DEV_SIMPLE_EXCEPTION(WhiskersError); * - Condition parameter: ......, where "" is optional * replaced (and recursively expanded) by the first part if the condition is true * and by the second (or empty string if missing) if the condition is false - * - Conditional string parameter: ...... - * Works similar to a conditional parameter where the checked condition is - * that the regular (string) parameter called "name" is non-empty. * - List parameter: <#list>... * The part between the tags is repeated as often as values are provided * in the mapping. Each list element can have its own parameter -> value mapping. + * - Conditional value parameter: ...... + * Works similar to a conditional parameter where the checked condition is + * that the string or list parameter called "name" is non-empty or contains + * no elements respectively. */ class Whiskers { From 454860d1f51c8f9f28454006619b5fc036ded23e Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Tue, 12 Oct 2021 15:25:28 +0200 Subject: [PATCH 34/62] CodeGen: Only output switch when it has cases --- Changelog.md | 1 + libsolidity/codegen/ir/IRGenerator.cpp | 6 ++--- .../debug_info_in_yul_snippet_escaping/output | 22 +++---------------- test/cmdlineTests/exp_base_literal/output | 2 +- test/cmdlineTests/name_simplifier/output | 4 ++-- test/cmdlineTests/revert_strings/output | 2 +- .../output.json | 20 ++++++++--------- .../output.json | 1 - .../standard_ir_requested/output.json | 2 +- .../standard_viair_requested/output.json | 18 +-------------- test/cmdlineTests/viair_abicoder_v1/output | 2 +- test/cmdlineTests/yul_optimizer_steps/output | 8 ------- .../output | 1 - .../yul_string_format_ascii/output.json | 2 +- .../output.json | 2 +- .../output.json | 2 +- .../yul_string_format_ascii_long/output.json | 2 +- .../yul_string_format_hex/output.json | 2 +- 18 files changed, 29 insertions(+), 70 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9dd650599..9a22fed2a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ Bugfixes: * Commandline Interface: Report output selection options unsupported by the selected input mode instead of ignoring them. * SMTChecker: Fix internal error in magic type access (``block``, ``msg``, ``tx``). * TypeChecker: Fix internal error when using user defined value types in public library functions. + * Yul IR Generator: Do not output empty switches/if-bodies for empty contracts. diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index c1bfce4e3..5a23dbea7 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -944,7 +944,7 @@ string IRGenerator::callValueCheck() string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) { Whiskers t(R"X( - if iszero(lt(calldatasize(), 4)) + if iszero(lt(calldatasize(), 4)) { let selector := (calldataload(0)) switch selector @@ -962,8 +962,8 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) } default {} - } - if iszero(calldatasize()) { } + } + if iszero(calldatasize()) { } )X"); t("shr224", m_utils.shiftRightFunction(224)); diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index a9dc1a290..b595a771e 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -44,14 +44,6 @@ object "C_2" { /// @src 0:265:278 "contract C {}" mstore(64, 128) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_224_unsigned(calldataload(0)) - switch selector - - default {} - } - if iszero(calldatasize()) { } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { @@ -175,7 +167,7 @@ object "D_27" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { @@ -413,14 +405,6 @@ object "D_27" { /// @src 0:265:278 "contract C {}" mstore(64, 128) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_224_unsigned(calldataload(0)) - switch selector - - default {} - } - if iszero(calldatasize()) { } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { @@ -499,7 +483,7 @@ object "D_27" { revert(pos, returndatasize()) } mstore(add(allocate_memory_array_string(), 32), "/*") - let memPtr := allocate_memory_array_string_482() + let memPtr := allocate_memory_array_string_480() mstore(add(memPtr, 32), 0x2f2a2a204073726320303a39363a313635202022636f6e74726163742044207b) mstore(add(memPtr, 64), shl(200, 0x2e2e2e22202a2f)) let memPos := mload(64) @@ -540,7 +524,7 @@ object "D_27" { memPtr := memPtr_1 mstore(memPtr_1, 2) } - function allocate_memory_array_string_482() -> memPtr + function allocate_memory_array_string_480() -> memPtr { let memPtr_1 := mload(64) let newFreePtr := add(memPtr_1, 96) diff --git a/test/cmdlineTests/exp_base_literal/output b/test/cmdlineTests/exp_base_literal/output index c4b71dcac..9c3efdc1f 100644 --- a/test/cmdlineTests/exp_base_literal/output +++ b/test/cmdlineTests/exp_base_literal/output @@ -63,7 +63,7 @@ object "C_81" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index 73c9cc1aa..44852d1a8 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -49,7 +49,7 @@ object "C_59" { for { } lt(src, srcEnd) { src := add(src, _2) } { if slt(sub(calldatasize(), src), _2) { revert(_1, _1) } - let value := allocate_memory_1174() + let value := allocate_memory_1172() mstore(value, calldataload(src)) mstore(dst, value) dst := add(dst, _2) @@ -67,7 +67,7 @@ object "C_59" { mstore(4, 0x41) revert(0, 0x24) } - function allocate_memory_1174() -> memPtr + function allocate_memory_1172() -> memPtr { memPtr := mload(64) let newFreePtr := add(memPtr, 32) diff --git a/test/cmdlineTests/revert_strings/output b/test/cmdlineTests/revert_strings/output index 718cf0ba9..9ca27eac4 100644 --- a/test/cmdlineTests/revert_strings/output +++ b/test/cmdlineTests/revert_strings/output @@ -78,7 +78,7 @@ object "C_15" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json index 0ba3b09a3..7a77d60f4 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -218,7 +218,7 @@ object \"C_54\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { @@ -639,7 +639,7 @@ object \"C_54\" { case 0x26121ff0 { if callvalue() { revert(_1, _1) } abi_decode(calldatasize()) - let ret := /** @src 0:286:305 \"constVar + immutVar\" */ checked_add_int256_568(/** @src 0:297:305 \"immutVar\" */ loadimmutable(\"8\")) + let ret := /** @src 0:286:305 \"constVar + immutVar\" */ checked_add_int256_566(/** @src 0:297:305 \"immutVar\" */ loadimmutable(\"8\")) /// @src 0:79:435 \"contract C...\" let memPos := mload(64) return(memPos, sub(abi_encode_int256(memPos, ret), memPos)) @@ -663,7 +663,7 @@ object \"C_54\" { if callvalue() { revert(_1, _1) } abi_decode(calldatasize()) let memPos_3 := mload(64) - return(memPos_3, sub(abi_encode_int256_567(memPos_3), memPos_3)) + return(memPos_3, sub(abi_encode_int256_565(memPos_3), memPos_3)) } } revert(0, 0) @@ -672,7 +672,7 @@ object \"C_54\" { { if slt(add(dataEnd, not(3)), 0) { revert(0, 0) } } - function abi_encode_int256_567(headStart) -> tail + function abi_encode_int256_565(headStart) -> tail { tail := add(headStart, 32) mstore(headStart, /** @src 0:124:126 \"41\" */ 0x29) @@ -689,7 +689,7 @@ object \"C_54\" { mstore(4, 0x11) revert(0, 0x24) } - function checked_add_int256_568(y) -> sum + function checked_add_int256_566(y) -> sum { if and(1, sgt(y, sub(shl(255, 1), 42))) { panic_error_0x11() } sum := add(/** @src 0:124:126 \"41\" */ 0x29, /** @src 0:79:435 \"contract C...\" */ y) @@ -1050,7 +1050,7 @@ object \"D_72\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { @@ -1479,7 +1479,7 @@ object \"D_72\" { case 0x26121ff0 { if callvalue() { revert(_1, _1) } abi_decode(calldatasize()) - let ret := /** @src 0:286:305 \"constVar + immutVar\" */ checked_add_int256_568(/** @src 0:297:305 \"immutVar\" */ loadimmutable(\"8\")) + let ret := /** @src 0:286:305 \"constVar + immutVar\" */ checked_add_int256_566(/** @src 0:297:305 \"immutVar\" */ loadimmutable(\"8\")) /// @src 1:91:166 \"contract D is C(3)...\" let memPos := mload(64) return(memPos, sub(abi_encode_int256(memPos, ret), memPos)) @@ -1503,7 +1503,7 @@ object \"D_72\" { if callvalue() { revert(_1, _1) } abi_decode(calldatasize()) let memPos_3 := mload(64) - return(memPos_3, sub(abi_encode_int256_567(memPos_3), memPos_3)) + return(memPos_3, sub(abi_encode_int256_565(memPos_3), memPos_3)) } } revert(0, 0) @@ -1512,7 +1512,7 @@ object \"D_72\" { { if slt(add(dataEnd, not(3)), 0) { revert(0, 0) } } - function abi_encode_int256_567(headStart) -> tail + function abi_encode_int256_565(headStart) -> tail { tail := add(headStart, 32) mstore(headStart, /** @src 0:124:126 \"41\" */ 0x29) @@ -1529,7 +1529,7 @@ object \"D_72\" { mstore(4, 0x11) revert(0, 0x24) } - function checked_add_int256_568(y) -> sum + function checked_add_int256_566(y) -> sum { if and(1, sgt(y, sub(shl(255, 1), 42))) { panic_error_0x11() } sum := add(/** @src 0:124:126 \"41\" */ 0x29, /** @src 1:91:166 \"contract D is C(3)...\" */ y) diff --git a/test/cmdlineTests/standard_irOptimized_requested/output.json b/test/cmdlineTests/standard_irOptimized_requested/output.json index c636adcc4..78499140c 100644 --- a/test/cmdlineTests/standard_irOptimized_requested/output.json +++ b/test/cmdlineTests/standard_irOptimized_requested/output.json @@ -47,7 +47,6 @@ object \"C_7\" { } default { } } - if iszero(calldatasize()) { } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { newValue := shr(224, value) } diff --git a/test/cmdlineTests/standard_ir_requested/output.json b/test/cmdlineTests/standard_ir_requested/output.json index 2c01878f3..2da612abc 100644 --- a/test/cmdlineTests/standard_ir_requested/output.json +++ b/test/cmdlineTests/standard_ir_requested/output.json @@ -62,7 +62,7 @@ object \"C_7\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/standard_viair_requested/output.json b/test/cmdlineTests/standard_viair_requested/output.json index 9ae88b90c..4bf34fd7a 100644 --- a/test/cmdlineTests/standard_viair_requested/output.json +++ b/test/cmdlineTests/standard_viair_requested/output.json @@ -43,14 +43,6 @@ object \"C_3\" { /// @src 0:79:92 \"contract C {}\" mstore(64, 128) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_224_unsigned(calldataload(0)) - switch selector - - default {} - } - if iszero(calldatasize()) { } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { @@ -139,7 +131,7 @@ object \"D_16\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { @@ -253,14 +245,6 @@ object \"D_16\" { /// @src 0:79:92 \"contract C {}\" mstore(64, 128) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_224_unsigned(calldataload(0)) - switch selector - - default {} - } - if iszero(calldatasize()) { } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/viair_abicoder_v1/output b/test/cmdlineTests/viair_abicoder_v1/output index 18d02a0e9..a23730702 100644 --- a/test/cmdlineTests/viair_abicoder_v1/output +++ b/test/cmdlineTests/viair_abicoder_v1/output @@ -63,7 +63,7 @@ object "test_11" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/yul_optimizer_steps/output b/test/cmdlineTests/yul_optimizer_steps/output index 478c844db..8e4cc7e88 100644 --- a/test/cmdlineTests/yul_optimizer_steps/output +++ b/test/cmdlineTests/yul_optimizer_steps/output @@ -31,16 +31,8 @@ object "C_7" { { /// @src 0:80:112 "contract C..." mstore(64, 128) - if iszero(lt(calldatasize(), 4)) - { - let selector := shift_right_unsigned(calldataload(0)) - pop(selector) - } - pop(iszero(calldatasize())) revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() } - function shift_right_unsigned(value) -> newValue - { newValue := shr(224, value) } function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } } diff --git a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output index d4c026105..63f08a35d 100644 --- a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output +++ b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output @@ -138,7 +138,6 @@ object "C_6" { return(memPos, sub(memEnd, memPos)) } } - pop(iszero(calldatasize())) revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() } function shift_right_unsigned(value) -> newValue diff --git a/test/cmdlineTests/yul_string_format_ascii/output.json b/test/cmdlineTests/yul_string_format_ascii/output.json index f68f984c7..ae7a926fe 100644 --- a/test/cmdlineTests/yul_string_format_ascii/output.json +++ b/test/cmdlineTests/yul_string_format_ascii/output.json @@ -62,7 +62,7 @@ object \"C_11\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json index e2757135e..59a93a7bf 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32/output.json @@ -62,7 +62,7 @@ object \"C_11\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json index c977d791d..79d35a338 100644 --- a/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_bytes32_from_number/output.json @@ -62,7 +62,7 @@ object \"C_11\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/yul_string_format_ascii_long/output.json b/test/cmdlineTests/yul_string_format_ascii_long/output.json index 19428f29d..932a5c28c 100644 --- a/test/cmdlineTests/yul_string_format_ascii_long/output.json +++ b/test/cmdlineTests/yul_string_format_ascii_long/output.json @@ -62,7 +62,7 @@ object \"C_11\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/yul_string_format_hex/output.json b/test/cmdlineTests/yul_string_format_hex/output.json index b17922a55..da8f873a3 100644 --- a/test/cmdlineTests/yul_string_format_hex/output.json +++ b/test/cmdlineTests/yul_string_format_hex/output.json @@ -62,7 +62,7 @@ object \"C_11\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { From b1dd0d0d02c96083ca8550f67dab7b54281a42e7 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 22 Sep 2021 15:14:31 +0200 Subject: [PATCH 35/62] Properly compute source mappings for immutables. --- Changelog.md | 1 + docs/internals/source_mappings.rst | 4 + docs/yul.rst | 2 + libevmasm/Assembly.cpp | 10 ++- libevmasm/Assembly.h | 2 +- libevmasm/AssemblyItem.cpp | 47 +++++++++- libevmasm/AssemblyItem.h | 18 ++-- libevmasm/ConstantOptimiser.cpp | 2 +- libevmasm/Inliner.cpp | 2 +- libevmasm/PeepholeOptimiser.cpp | 4 +- test/libevmasm/Assembler.cpp | 90 ++++++++++++++++++- ..._long_name_does_not_end_up_in_bytecode.yul | 2 +- 12 files changed, 164 insertions(+), 20 deletions(-) diff --git a/Changelog.md b/Changelog.md index 88b9bde88..6fd65df79 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Compiler Features: Bugfixes: + * Code Generator: Fix constructor source mappings for immutables. * Commandline Interface: Fix extra newline character being appended to sources passed through standard input, affecting their hashes. * Commandline Interface: Report output selection options unsupported by the selected input mode instead of ignoring them. * SMTChecker: Fix internal error in magic type access (``block``, ``msg``, ``tx``). diff --git a/docs/internals/source_mappings.rst b/docs/internals/source_mappings.rst index fbb84e2d1..11027b8ac 100644 --- a/docs/internals/source_mappings.rst +++ b/docs/internals/source_mappings.rst @@ -64,3 +64,7 @@ This means the following source mappings represent the same information: ``1:2:1;1:9:1;2:1:2;2:1:2;2:1:2`` ``1:2:1;:9;2:1:2;;`` + +Important to note is that when the :ref:`verbatim ` builtin is used, +the source mappings will be invalid: The builtin is considered a single +instruction instead of potentially multiple. diff --git a/docs/yul.rst b/docs/yul.rst index e4819ff22..0a90a2825 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -1002,6 +1002,8 @@ within one Yul subobject. If at least one ``memoryguard`` call is found in a sub the additional optimiser steps will be run on it. +.. _yul-verbatim: + verbatim ^^^^^^^^ diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 82bf2be71..12c7be230 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -48,11 +48,11 @@ using namespace solidity::evmasm; using namespace solidity::langutil; using namespace solidity::util; -AssemblyItem const& Assembly::append(AssemblyItem const& _i) +AssemblyItem const& Assembly::append(AssemblyItem _i) { assertThrow(m_deposit >= 0, AssemblyException, "Stack underflow."); m_deposit += static_cast(_i.deposit()); - m_items.emplace_back(_i); + m_items.emplace_back(move(_i)); if (!m_items.back().location().isValid() && m_currentSourceLocation.isValid()) m_items.back().setLocation(m_currentSourceLocation); m_items.back().m_modifierDepth = m_currentModifierDepth; @@ -68,7 +68,7 @@ unsigned Assembly::codeSize(unsigned subTagSize) const ret += i.second.size(); for (AssemblyItem const& i: m_items) - ret += i.bytesRequired(tagSize); + ret += i.bytesRequired(tagSize, Precision::Approximate); if (numberEncodingSize(ret) <= tagSize) return static_cast(ret); } @@ -696,8 +696,11 @@ LinkerObject const& Assembly::assemble() const break; case PushImmutable: ret.bytecode.push_back(static_cast(Instruction::PUSH32)); + // Maps keccak back to the "identifier" string of that immutable. ret.immutableReferences[i.data()].first = m_immutables.at(i.data()); + // Record the bytecode offset of the PUSH32 argument. ret.immutableReferences[i.data()].second.emplace_back(ret.bytecode.size()); + // Advance bytecode by 32 bytes (default initialized). ret.bytecode.resize(ret.bytecode.size() + 32); break; case VerbatimBytecode: @@ -705,6 +708,7 @@ LinkerObject const& Assembly::assemble() const break; case AssignImmutable: { + // Expect 2 elements on stack (source, dest_base) auto const& offsets = immutableReferencesBySub[i.data()].second; for (size_t i = 0; i < offsets.size(); ++i) { diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index b532834f5..f768ffe31 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -65,7 +65,7 @@ public: AssemblyItem newPushImmutable(std::string const& _identifier); AssemblyItem newImmutableAssignment(std::string const& _identifier); - AssemblyItem const& append(AssemblyItem const& _i); + AssemblyItem const& append(AssemblyItem _i); AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); } template Assembly& operator<<(T const& _d) { append(_d); return *this; } diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index a34870eda..eeeadb3ef 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -65,7 +65,7 @@ void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag) setData(data); } -size_t AssemblyItem::bytesRequired(size_t _addressLength) const +size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision) const { switch (m_type) { @@ -87,10 +87,25 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength) const case PushImmutable: return 1 + 32; case AssignImmutable: - if (m_immutableOccurrences) - return 1 + (3 + 32) * *m_immutableOccurrences; + { + unsigned long immutableOccurrences = 0; + + // Skip exact immutables count if no precise count was requested + if (_precision == Precision::Approximate) + immutableOccurrences = 1; // Assume one immut. ref. else - return 1 + (3 + 32) * 1024; // 1024 occurrences are beyond the maximum code size anyways. + { + solAssert(m_immutableOccurrences, "No immutable references. `bytesRequired()` called before assembly()?"); + immutableOccurrences = m_immutableOccurrences.value(); + } + + if (immutableOccurrences != 0) + // (DUP DUP PUSH ADD MSTORE)* (PUSH ADD MSTORE) + return (immutableOccurrences - 1) * (5 + 32) + (3 + 32); + else + // POP POP + return 2; + } case VerbatimBytecode: return std::get<2>(*m_verbatimBytecode).size(); default: @@ -322,6 +337,26 @@ ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item) return _out; } +size_t AssemblyItem::opcodeCount() const noexcept +{ + switch (m_type) + { + case AssemblyItemType::AssignImmutable: + // Append empty items if this AssignImmutable was referenced more than once. + // For n immutable occurrences the first (n - 1) occurrences will + // generate 5 opcodes and the last will generate 3 opcodes, + // because it is reusing the 2 top-most elements on the stack. + solAssert(m_immutableOccurrences, ""); + + if (m_immutableOccurrences.value() != 0) + return (*m_immutableOccurrences - 1) * 5 + 3; + else + return 2; // two POP's + default: + return 1; + } +} + std::string AssemblyItem::computeSourceMapping( AssemblyItems const& _items, map const& _sourceIndicesMap @@ -334,6 +369,7 @@ std::string AssemblyItem::computeSourceMapping( int prevSourceIndex = -1; int prevModifierDepth = -1; char prevJump = 0; + for (auto const& item: _items) { if (!ret.empty()) @@ -402,6 +438,9 @@ std::string AssemblyItem::computeSourceMapping( } } + if (item.opcodeCount() > 1) + ret += string(item.opcodeCount() - 1, ';'); + prevStart = location.start; prevLength = length; prevSourceIndex = sourceIndex; diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index f1b2b5043..1cbfe768d 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,8 @@ enum AssemblyItemType VerbatimBytecode ///< Contains data that is inserted into the bytecode code section without modification. }; +enum class Precision { Precise , Approximate }; + class Assembly; class AssemblyItem; using AssemblyItems = std::vector; @@ -147,7 +150,10 @@ public: /// @returns an upper bound for the number of bytes required by this item, assuming that /// the value of a jump tag takes @a _addressLength bytes. - size_t bytesRequired(size_t _addressLength) const; + /// @param _precision Whether to return a precise count (which involves + /// counting immutable references which are only set after + /// a call to `assemble()`) or an approx. count. + size_t bytesRequired(size_t _addressLength, Precision _precision = Precision::Precise) const; size_t arguments() const; size_t returnValues() const; size_t deposit() const { return returnValues() - arguments(); } @@ -169,9 +175,11 @@ public: size_t m_modifierDepth = 0; - void setImmutableOccurrences(size_t _n) const { m_immutableOccurrences = std::make_shared(_n); } + void setImmutableOccurrences(size_t _n) const { m_immutableOccurrences = _n; } private: + size_t opcodeCount() const noexcept; + AssemblyItemType m_type; Instruction m_instruction; ///< Only valid if m_type == Operation std::shared_ptr m_data; ///< Only valid if m_type != Operation @@ -184,14 +192,14 @@ private: /// e.g. PushSubSize, PushTag, PushSub, etc. mutable std::shared_ptr m_pushedValue; /// Number of PushImmutable's with the same hash. Only used for AssignImmutable. - mutable std::shared_ptr m_immutableOccurrences; + mutable std::optional m_immutableOccurrences; }; -inline size_t bytesRequired(AssemblyItems const& _items, size_t _addressLength) +inline size_t bytesRequired(AssemblyItems const& _items, size_t _addressLength, Precision _precision = Precision::Precise) { size_t size = 0; for (AssemblyItem const& item: _items) - size += item.bytesRequired(_addressLength); + size += item.bytesRequired(_addressLength, _precision); return size; } diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 6800baef3..a639bc6fc 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -103,7 +103,7 @@ bigint ConstantOptimisationMethod::dataGas(bytes const& _data) const size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items) { - return evmasm::bytesRequired(_items, 3); // assume 3 byte addresses + return evmasm::bytesRequired(_items, 3, Precision::Approximate); // assume 3 byte addresses } void ConstantOptimisationMethod::replaceConstants( diff --git a/libevmasm/Inliner.cpp b/libevmasm/Inliner.cpp index 8d95bdc3b..527e6ae38 100644 --- a/libevmasm/Inliner.cpp +++ b/libevmasm/Inliner.cpp @@ -63,7 +63,7 @@ template uint64_t codeSize(RangeType const& _itemRange) { return ranges::accumulate(_itemRange | ranges::views::transform( - [](auto const& _item) { return _item.bytesRequired(2); } + [](auto const& _item) { return _item.bytesRequired(2, Precision::Approximate); } ), 0u); } /// @returns the tag id, if @a _item is a PushTag or Tag into the current subassembly, nullopt otherwise. diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 0ee0b5efd..8e4a09fcc 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -388,6 +388,8 @@ size_t numberOfPops(AssemblyItems const& _items) bool PeepholeOptimiser::optimise() { + // Avoid referencing immutables too early by using approx. counting in bytesRequired() + auto const approx = evmasm::Precision::Approximate; OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)}; while (state.i < m_items.size()) applyMethods( @@ -398,7 +400,7 @@ bool PeepholeOptimiser::optimise() ); if (m_optimisedItems.size() < m_items.size() || ( m_optimisedItems.size() == m_items.size() && ( - evmasm::bytesRequired(m_optimisedItems, 3) < evmasm::bytesRequired(m_items, 3) || + evmasm::bytesRequired(m_optimisedItems, 3, approx) < evmasm::bytesRequired(m_items, 3, approx) || numberOfPops(m_optimisedItems) > numberOfPops(m_items) ) )) diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 0c1e4dbad..c7f28f654 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -21,15 +21,16 @@ * Tests for the assembler. */ -#include #include +#include +#include #include +#include +#include #include #include -#include -#include using namespace std; using namespace solidity::langutil; @@ -165,6 +166,89 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) ); } +BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) +{ + // Tests for 1, 2, 3 number of immutables. + for (int numImmutables = 1; numImmutables <= 3; ++numImmutables) + { + BOOST_TEST_MESSAGE("NumImmutables: "s + to_string(numImmutables)); + // Tests for the cases 1, 2, 3 occurrences of an immutable reference. + for (int numActualRefs = 1; numActualRefs <= 3; ++numActualRefs) + { + BOOST_TEST_MESSAGE("NumActualRefs: "s + to_string(numActualRefs)); + auto const NumExpectedMappings = + ( + 2 + // PUSH PUSH + (numActualRefs - 1) * 5 + // DUP DUP PUSH ADD MTOSRE + 3 // PUSH ADD MSTORkhbE + ) * numImmutables; + + auto constexpr NumSubs = 1; + auto constexpr NumOpcodesWithoutMappings = + NumSubs + // PUSH for every sub assembly + 1; // INVALID + + auto assemblyName = make_shared("root.asm"); + auto subName = make_shared("sub.asm"); + + map indices = { + { *assemblyName, 0 }, + { *subName, 1 } + }; + + auto subAsm = make_shared(); + for (char i = 0; i < numImmutables; ++i) + { + for (int r = 0; r < numActualRefs; ++r) + { + subAsm->setSourceLocation(SourceLocation{10*i, 10*i + 6 + r, subName}); + subAsm->appendImmutable(string(1, char('a' + i))); // "a", "b", ... + } + } + + Assembly assembly; + for (char i = 1; i <= numImmutables; ++i) + { + assembly.setSourceLocation({10*i, 10*i + 3+i, assemblyName}); + assembly.append(u256(0x71)); // immutble value + assembly.append(u256(0)); // target... modules? + assembly.appendImmutableAssignment(string(1, char('a' + i - 1))); + } + + assembly.appendSubroutine(subAsm); + + checkCompilation(assembly); + + string const sourceMappings = AssemblyItem::computeSourceMapping(assembly.items(), indices); + auto const numberOfMappings = std::count(sourceMappings.begin(), sourceMappings.end(), ';'); + + LinkerObject const& obj = assembly.assemble(); + string const disassembly = disassemble(obj.bytecode, "\n"); + auto const numberOfOpcodes = std::count(disassembly.begin(), disassembly.end(), '\n'); + + #if 0 // {{{ debug prints + { + LinkerObject const& subObj = assembly.sub(0).assemble(); + string const subDisassembly = disassemble(subObj.bytecode, "\n"); + cout << '\n'; + cout << "### immutables: " << numImmutables << ", refs: " << numActualRefs << '\n'; + cout << " - srcmap: \"" << sourceMappings << "\"\n"; + cout << " - src mappings: " << numberOfMappings << '\n'; + cout << " - opcodes: " << numberOfOpcodes << '\n'; + cout << " - subs: " << assembly.numSubs() << '\n'; + cout << " - sub opcodes " << std::count(subDisassembly.begin(), subDisassembly.end(), '\n') << '\n'; + cout << " - sub srcmaps " << AssemblyItem::computeSourceMapping(subAsm->items(), indices) << '\n'; + cout << " - main bytecode:\n\t" << disassemble(obj.bytecode, "\n\t"); + cout << "\r - sub bytecode:\n\t" << disassemble(subObj.bytecode, "\n\t"); + } + #endif // }}} + + BOOST_REQUIRE_EQUAL(NumExpectedMappings, numberOfMappings); + BOOST_REQUIRE_EQUAL(NumExpectedMappings, numberOfOpcodes - NumOpcodesWithoutMappings); + } + } +} + BOOST_AUTO_TEST_CASE(immutable) { map indices = { diff --git a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul index a208d15a5..dcc41e7a0 100644 --- a/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul +++ b/test/libyul/objectCompiler/immutable_long_name_does_not_end_up_in_bytecode.yul @@ -17,4 +17,4 @@ object "a" { // assignImmutable("0x85a5b1db611c82c46f5fa18e39ae218397536256c451e5de155a86de843a9ad6") // Bytecode: 73123456789012345678901234567890123456789060005050 // Opcodes: PUSH20 0x1234567890123456789012345678901234567890 PUSH1 0x0 POP POP -// SourceMappings: 167:42:0:-:0;58:1;32:187 +// SourceMappings: 167:42:0:-:0;58:1;32:187; From 59d8f50518306b8bb75b014cb6fca5708bbb4345 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 12 Oct 2021 18:07:06 +0200 Subject: [PATCH 36/62] Fix tests. --- .../cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output | 2 +- .../debug_info_in_yul_and_evm_asm_print_location_only/output | 2 +- .../debug_info_in_yul_and_evm_asm_print_none/output | 2 +- .../output.json | 2 +- .../output.json | 2 +- .../output.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output index 157594b2b..31b0ae463 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output @@ -118,7 +118,7 @@ object "C_6" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output index 505e734b9..4d7210d37 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output @@ -118,7 +118,7 @@ object "C_6" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output index c8f76f990..0c0fbfa1e 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output @@ -111,7 +111,7 @@ object "C_6" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json index 4ef790de3..3c630bb2d 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json @@ -124,7 +124,7 @@ object \"C_6\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json index 2aebdc0f2..1f728995d 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json @@ -124,7 +124,7 @@ object \"C_6\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json index be369ef1a..8d19f60a3 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json @@ -117,7 +117,7 @@ object \"C_6\" { default {} } - if iszero(calldatasize()) { } + revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() function shift_right_224_unsigned(value) -> newValue { From a5ed732fd383dee196931badcb3c69ffb048a14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 11 Oct 2021 13:03:51 +0200 Subject: [PATCH 37/62] CommandLineInterface: Rename m_error to m_outputFailed --- solc/CommandLineInterface.cpp | 6 +++--- solc/CommandLineInterface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 3b26b6c83..dc07b499d 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -553,7 +553,7 @@ void CommandLineInterface::createFile(string const& _fileName, string const& _da if (fs::exists(pathName) && !m_options.output.overwriteFiles) { serr() << "Refusing to overwrite existing file \"" << pathName << "\" (use --overwrite to force)." << endl; - m_error = true; + m_outputFailed = true; return; } ofstream outFile(pathName); @@ -561,7 +561,7 @@ void CommandLineInterface::createFile(string const& _fileName, string const& _da if (!outFile) { serr() << "Could not write to file \"" << pathName << "\"." << endl; - m_error = true; + m_outputFailed = true; return; } } @@ -855,7 +855,7 @@ bool CommandLineInterface::actOnInput() solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, ""); outputCompilationResults(); } - return !m_error; + return !m_outputFailed; } bool CommandLineInterface::link() diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 5504e51bb..1ca40568c 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -121,7 +121,7 @@ private: std::ostream& m_sout; std::ostream& m_serr; bool m_hasOutput = false; - bool m_error = false; ///< If true, some error occurred. + bool m_outputFailed = false; ///< If true, creation or write to some of the output files failed. FileReader m_fileReader; std::optional m_standardJsonInput; std::unique_ptr m_compiler; From 01327d6ef1bc66c558eadbdac82e402109797544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 12 Oct 2021 13:36:24 +0200 Subject: [PATCH 38/62] CommandLineInterface: Don't return zero exit code when writing linked files to disk fails --- Changelog.md | 1 + solc/CommandLineInterface.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 88b9bde88..142682fea 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ Compiler Features: Bugfixes: * Commandline Interface: Fix extra newline character being appended to sources passed through standard input, affecting their hashes. * Commandline Interface: Report output selection options unsupported by the selected input mode instead of ignoring them. + * Commandline Interface: Don't return zero exit code when writing linked files to disk fails. * SMTChecker: Fix internal error in magic type access (``block``, ``msg``, ``tx``). * TypeChecker: Fix internal error when using user defined value types in public library functions. * Yul IR Generator: Do not output empty switches/if-bodies for empty contracts. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index dc07b499d..6c24b7742 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -937,6 +937,7 @@ void CommandLineInterface::writeLinkedFiles() if (!outFile) { serr() << "Could not write to file " << src.first << ". Aborting." << endl; + m_outputFailed = true; return; } } From 5b926bee3f0ea71dae9aeee3e60803a1d4106ee6 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Mon, 5 Jul 2021 13:27:57 +0200 Subject: [PATCH 39/62] [docs] contributing.rst: Documents evmone.so loading search paths. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Åšliwak --- docs/contributing.rst | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 6b2db9546..5f3315f1b 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -86,12 +86,10 @@ Running the Compiler Tests Prerequisites ------------- -Some tests require the `evmone `_ -library, others require `libz3 `_. The test script -tries to discover the location of the ``evmone`` library, which can be located -in the current directory, installed on the system level, or the ``deps`` folder -in the project top level. The required file is called ``libevmone.so`` on Linux -systems, ``evmone.dll`` on Windows systems and ``libevmone.dylib`` on macOS. +For running all compiler tests you may want to optionally install a few +dependencies (`evmone `_, +`libz3 `_, and +`libhera `_). On macOS some of the testing scripts expect GNU coreutils to be installed. This can be easiest accomplished using Homebrew: ``brew install coreutils``. @@ -108,13 +106,29 @@ including those bundled into the `Boost C++ Test Framework `_ -and place it in the project root path or inside the ``deps`` folder. +The test system automatically tries to discover the location of +the `evmone `_ for running the semantic tests. + +The ``evmone`` library must be located in the ``deps`` or ``deps/lib`` directory relative to the +current working directory or up to the project root. Alternatively an explicit location +to the ``evmone`` shared object can be specified via the ``ETH_EVMONE`` environment variable. + +If running semantic tests is not required, the command line +parameter ``--no-semantic-tests`` must be passed to ``./scripts/soltest.sh``. + +The tests that use ``evmone`` are ``libsolidity/semanticTests``, ``libsolidity/GasCosts``, +``libsolidity/SolidityEndToEndTest``. + +Running Ewasm tests is disabled by default and can be explicitly enabled +via ``./scripts/soltest.sh --ewasm`` and requires `hera `_ +to be found by ``soltest``. +The ``hera`` library can is using the same search path as described above for ``evmone``. + +The ``evmone`` and ``hera`` libraries should both end with the file name +extension ``.so`` on Linux, ``.dll`` on Windows systems and ``.dylib`` on macOS. + +For running SMT tests, the ``libz3`` library must be installed and locatable +by ``cmake`` during compiler configure stage. If the ``libz3`` library is not installed on your system, you should disable the SMT tests by exporting ``SMT_FLAGS=--no-smt`` before running ``./scripts/tests.sh`` or From 1a931a510879f378db42df86d1207fe546e8b4b9 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 12 Aug 2021 15:29:16 +0200 Subject: [PATCH 40/62] Make use of inner loops. --- libsolidity/interface/OptimiserSettings.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libsolidity/interface/OptimiserSettings.h b/libsolidity/interface/OptimiserSettings.h index 578a5519a..5317acee4 100644 --- a/libsolidity/interface/OptimiserSettings.h +++ b/libsolidity/interface/OptimiserSettings.h @@ -44,20 +44,20 @@ struct OptimiserSettings static char constexpr DefaultYulOptimiserSteps[] = "dhfoDgvulfnTUtnIf" // None of these can make stack problems worse "[" - "xarrscLM" // Turn into SSA and simplify + "xa[r]scLM" // Turn into SSA and simplify "cCTUtTOntnfDIul" // Perform structural simplification "Lcul" // Simplify again - "Vcul jj" // Reverse SSA + "Vcul [j]" // Reverse SSA // should have good "compilability" property here. "Tpeul" // Run functional expression inliner - "xarulrul" // Prune a bit more in SSA - "xarrcL" // Turn into SSA again and simplify + "xa[rul]" // Prune a bit more in SSA + "xa[r]cL" // Turn into SSA again and simplify "gvif" // Run full inliner - "CTUcarrLsTFOtfDncarrIulc" // SSA plus simplify + "CTUca[r]LsTFOtfDnca[r]Iulc" // SSA plus simplify "]" - "jmuljuljul VcTOcul jmul"; // Make source short and pretty + "jmul[jul] VcTOcul jmul"; // Make source short and pretty /// No optimisations at all - not recommended. static OptimiserSettings none() From b96de320e2a121ccd3267863ad33affa10cfc881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 21 Jan 2021 16:17:01 +0100 Subject: [PATCH 41/62] Fix the simplest pylint warnings (variables/imports, semicolons, etc) and re-enable them in pylintrc --- scripts/bytecodecompare/prepare_report.py | 2 +- scripts/endToEndExtraction/remove-testcases.py | 4 ++-- scripts/endToEndExtraction/verify-testcases.py | 4 ++-- scripts/error_codes.py | 4 ++-- scripts/fix_homebrew_paths_in_standalone_zip.py | 7 ++++--- scripts/gas_diff_stats.py | 6 +++--- scripts/isolate_tests.py | 1 - scripts/pylint_all.py | 1 - scripts/pylintrc | 13 ++----------- scripts/regressions.py | 4 ++-- scripts/splitSources.py | 2 -- test/formal/move_and_across_shr_128.py | 8 ++++---- test/formal/signextend.py | 1 - test/formal/signextend_shr.py | 1 - test/formal/util.py | 10 +++++----- 15 files changed, 27 insertions(+), 41 deletions(-) diff --git a/scripts/bytecodecompare/prepare_report.py b/scripts/bytecodecompare/prepare_report.py index 33463f198..9d35b9988 100755 --- a/scripts/bytecodecompare/prepare_report.py +++ b/scripts/bytecodecompare/prepare_report.py @@ -413,7 +413,7 @@ def commandline_parser() -> ArgumentParser: action='store_true', help="Immediately exit and print compiler output if the compiler exits with an error.", ) - return parser; + return parser if __name__ == "__main__": diff --git a/scripts/endToEndExtraction/remove-testcases.py b/scripts/endToEndExtraction/remove-testcases.py index b1dc75b6c..28822e044 100755 --- a/scripts/endToEndExtraction/remove-testcases.py +++ b/scripts/endToEndExtraction/remove-testcases.py @@ -39,7 +39,7 @@ def colorize(left, right, id): reset = "\x1b[0m" colors = [red, yellow] color = colors[id % len(colors)] - function, arguments, results = parse_call(right) + function, _arguments, _results = parse_call(right) left = left.replace("compileAndRun", color + "compileAndRun" + reset) right = right.replace("constructor", color + "constructor" + reset) if function: @@ -158,7 +158,7 @@ def main(argv): interactive = False input_file = None try: - opts, args = getopt.getopt(argv, "if:") + opts, _args = getopt.getopt(argv, "if:") except getopt.GetoptError: print("./remove-testcases.py [-i] [-f ]") sys.exit(1) diff --git a/scripts/endToEndExtraction/verify-testcases.py b/scripts/endToEndExtraction/verify-testcases.py index c86a993dc..8e1c60a79 100755 --- a/scripts/endToEndExtraction/verify-testcases.py +++ b/scripts/endToEndExtraction/verify-testcases.py @@ -158,7 +158,7 @@ class TraceAnalyser: for trace_id, trace in enumerate(left.traces): left_trace = trace right_trace = right.traces[trace_id] - assert (left_trace.kind == right_trace.kind) + assert left_trace.kind == right_trace.kind if str(left_trace) != str(right_trace): mismatch_info = " " + str(left_trace) + "\n" mismatch_info += " " + str(right_trace) + "\n" @@ -179,7 +179,7 @@ def main(argv): extracted_tests_trace_file = None end_to_end_trace_file = None try: - opts, args = getopt.getopt(argv, "s:e:") + opts, _args = getopt.getopt(argv, "s:e:") except getopt.GetoptError: print("verify-testcases.py [-s ] [-e ]") sys.exit(2) diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 8d919e41b..9290211a2 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -261,9 +261,9 @@ def main(argv): no_confirm = False examine_coverage = False next_id = False - opts, args = getopt.getopt(argv, "", ["check", "fix", "no-confirm", "examine-coverage", "next"]) + opts, _args = getopt.getopt(argv, "", ["check", "fix", "no-confirm", "examine-coverage", "next"]) - for opt, arg in opts: + for opt, _arg in opts: if opt == "--check": check = True elif opt == "--fix": diff --git a/scripts/fix_homebrew_paths_in_standalone_zip.py b/scripts/fix_homebrew_paths_in_standalone_zip.py index 95120f760..43f26795c 100755 --- a/scripts/fix_homebrew_paths_in_standalone_zip.py +++ b/scripts/fix_homebrew_paths_in_standalone_zip.py @@ -49,9 +49,10 @@ def readDependencies(fname): if line[0] == '\t': library = line.split(' ', 1)[0][1:] if (library.startswith("/usr/local/lib") or - library.startswith("/usr/local/opt") or - library.startswith("/Users/")): - if (os.path.basename(library) != os.path.basename(fname)): + library.startswith("/usr/local/opt") or + library.startswith("/Users/") + ): + if os.path.basename(library) != os.path.basename(fname): command = "install_name_tool -change " + \ library + " @executable_path/./" + \ os.path.basename(library) + " " + fname diff --git a/scripts/gas_diff_stats.py b/scripts/gas_diff_stats.py index 1e86e2836..5c7aa5338 100644 --- a/scripts/gas_diff_stats.py +++ b/scripts/gas_diff_stats.py @@ -20,7 +20,7 @@ repository. The changes are compared against ``origin/develop``. import subprocess from pathlib import Path from enum import Enum -from parsec import * +from parsec import generate, ParseError, regex, string from tabulate import tabulate class Kind(Enum): @@ -56,10 +56,10 @@ def diff_string() -> (Kind, Diff, int): -// gas irOptimized: 138070 """ - diff_kind = yield (minus | plus) + diff_kind = yield minus | plus yield comment yield space - codegen_kind = yield (gas_ir_optimized ^ gas_legacy_optimized ^ gas_legacy) + codegen_kind = yield gas_ir_optimized ^ gas_legacy_optimized ^ gas_legacy yield colon yield space val = yield number() diff --git a/scripts/isolate_tests.py b/scripts/isolate_tests.py index 93cf2755c..1e2170e82 100755 --- a/scripts/isolate_tests.py +++ b/scripts/isolate_tests.py @@ -6,7 +6,6 @@ # into files for e.g. fuzz testing as # scripts/isolate_tests.py test/libsolidity/* -import sys import re import os import hashlib diff --git a/scripts/pylint_all.py b/scripts/pylint_all.py index 7b8924b8a..8dbe6a7fc 100755 --- a/scripts/pylint_all.py +++ b/scripts/pylint_all.py @@ -9,7 +9,6 @@ from os import path, walk from sys import exit from textwrap import dedent import subprocess -import sys PROJECT_ROOT = path.dirname(path.dirname(path.realpath(__file__))) PYLINT_RCFILE = f"{PROJECT_ROOT}/scripts/pylintrc" diff --git a/scripts/pylintrc b/scripts/pylintrc index ed63c9256..50dbebee0 100644 --- a/scripts/pylintrc +++ b/scripts/pylintrc @@ -24,24 +24,15 @@ disable= duplicate-code, invalid-name, missing-docstring, - mixed-indentation, no-else-return, no-self-use, pointless-string-statement, redefined-builtin, redefined-outer-name, singleton-comparison, - superfluous-parens, too-few-public-methods, - trailing-newlines, - undefined-variable, - ungrouped-imports, - unnecessary-semicolon, - unused-import, - unused-variable, - unused-wildcard-import, - useless-object-inheritance, - wildcard-import + too-many-public-methods, + ungrouped-imports [BASIC] diff --git a/scripts/regressions.py b/scripts/regressions.py index 1efbb48b5..046044197 100755 --- a/scripts/regressions.py +++ b/scripts/regressions.py @@ -11,7 +11,7 @@ import time DESCRIPTION = """Regressor is a tool to run regression tests in a CI env.""" -class PrintDotsThread(object): +class PrintDotsThread: """Prints a dot every "interval" (default is 300) seconds""" def __init__(self, interval=300): @@ -30,7 +30,7 @@ class PrintDotsThread(object): print(".") time.sleep(self.interval) -class regressor(): +class regressor: _re_sanitizer_log = re.compile(r"""ERROR: (libFuzzer|UndefinedBehaviorSanitizer)""") def __init__(self, description, args): diff --git a/scripts/splitSources.py b/scripts/splitSources.py index 3d1c8ef45..181741f9c 100755 --- a/scripts/splitSources.py +++ b/scripts/splitSources.py @@ -44,9 +44,7 @@ def writeSourceToFile(lines): os.system("mkdir -p " + filePath) with open(srcName, mode='a+', encoding='utf8', newline='') as f: createdSources.append(srcName) - i = 0 for idx, line in enumerate(lines[1:]): - # write to file if line[:12] != "==== Source:": f.write(line) diff --git a/test/formal/move_and_across_shr_128.py b/test/formal/move_and_across_shr_128.py index df673ff59..7ec4a65c1 100644 --- a/test/formal/move_and_across_shr_128.py +++ b/test/formal/move_and_across_shr_128.py @@ -25,12 +25,12 @@ BitWidth = BitVecVal(n_bits, n_bits) rule.require(ULT(B, BitWidth)) # Non optimized result -nonopt_1 = SHR(B, AND(X, A)); -nonopt_2 = SHR(B, AND(A, X)); +nonopt_1 = SHR(B, AND(X, A)) +nonopt_2 = SHR(B, AND(A, X)) # Optimized result -Mask = SHR(B, A); -opt = AND(SHR(B, X), Mask); +Mask = SHR(B, A) +opt = AND(SHR(B, X), Mask) rule.check(nonopt_1, opt) rule.check(nonopt_2, opt) diff --git a/test/formal/signextend.py b/test/formal/signextend.py index 32d374261..483fcca56 100644 --- a/test/formal/signextend.py +++ b/test/formal/signextend.py @@ -34,4 +34,3 @@ rule3.check( SIGNEXTEND(A, SIGNEXTEND(B, X)), SIGNEXTEND(If(ULT(A, B), A, B), X) ) - diff --git a/test/formal/signextend_shr.py b/test/formal/signextend_shr.py index 4364e6a23..aa44a2345 100644 --- a/test/formal/signextend_shr.py +++ b/test/formal/signextend_shr.py @@ -28,4 +28,3 @@ rule.check( SIGNEXTEND(A, SHR(B, X)), SAR(B, X) ) - diff --git a/test/formal/util.py b/test/formal/util.py index ec98f9c81..8331a1fcc 100644 --- a/test/formal/util.py +++ b/test/formal/util.py @@ -1,27 +1,27 @@ from z3 import * def BVUnsignedUpCast(x, n_bits): - assert(x.size() <= n_bits) + assert x.size() <= n_bits if x.size() < n_bits: return Concat(BitVecVal(0, n_bits - x.size()), x) else: return x def BVUnsignedMax(type_bits, n_bits): - assert(type_bits <= n_bits) + assert type_bits <= n_bits return BitVecVal((1 << type_bits) - 1, n_bits) def BVSignedUpCast(x, n_bits): - assert(x.size() <= n_bits) + assert x.size() <= n_bits if x.size() < n_bits: return Concat(If(x < 0, BitVecVal(-1, n_bits - x.size()), BitVecVal(0, n_bits - x.size())), x) else: return x def BVSignedMax(type_bits, n_bits): - assert(type_bits <= n_bits) + assert type_bits <= n_bits return BitVecVal((1 << (type_bits - 1)) - 1, n_bits) def BVSignedMin(type_bits, n_bits): - assert(type_bits <= n_bits) + assert type_bits <= n_bits return BitVecVal(-(1 << (type_bits - 1)), n_bits) From fc0fe4f022e59bdacb4e1d1d68b8707787475b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 21 Jan 2021 16:18:24 +0100 Subject: [PATCH 42/62] isolate_tests.py: Silence spurious pylint warning about isfile() being unused --- scripts/wasm-rebuild/docker-scripts/isolate_tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/wasm-rebuild/docker-scripts/isolate_tests.py b/scripts/wasm-rebuild/docker-scripts/isolate_tests.py index 635ebcc31..c447c1e67 100755 --- a/scripts/wasm-rebuild/docker-scripts/isolate_tests.py +++ b/scripts/wasm-rebuild/docker-scripts/isolate_tests.py @@ -7,7 +7,8 @@ import sys import re import os import hashlib -from os.path import join, isfile +# Pylint for some reason insists that isfile() is unused +from os.path import join, isfile # pylint: disable=unused-import def extract_test_cases(path): From 4ed86edbc407d4f7b7f7dba93d65be2e4d560c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 21 Jan 2021 16:20:22 +0100 Subject: [PATCH 43/62] test/formal: Get rid of wildcard imports --- test/formal/byte_big.py | 3 ++- test/formal/byte_equivalence.py | 3 ++- test/formal/checked_int_add.py | 5 +++-- test/formal/checked_int_div.py | 5 +++-- test/formal/checked_int_mul_16.py | 5 +++-- test/formal/checked_int_sub.py | 5 +++-- test/formal/checked_uint_add.py | 5 +++-- test/formal/checked_uint_mul_16.py | 5 +++-- test/formal/checked_uint_sub.py | 5 +++-- test/formal/combine_byte_shl.py | 3 ++- test/formal/combine_byte_shr_1.py | 3 ++- test/formal/combine_byte_shr_2.py | 3 ++- test/formal/combine_div_shl_one_32.py | 3 ++- test/formal/combine_mul_shl_one_64.py | 3 ++- test/formal/combine_shl_shr_by_constant_64.py | 3 ++- test/formal/combine_shr_shl_by_constant_64.py | 3 ++- test/formal/eq_sub.py | 3 ++- test/formal/exp_neg_one.py | 5 +++-- test/formal/exp_to_shl.py | 4 ++-- test/formal/move_and_across_shl_128.py | 3 ++- test/formal/move_and_across_shr_128.py | 3 ++- test/formal/move_and_inside_or.py | 4 +++- test/formal/opcodes.py | 2 +- test/formal/repeated_and.py | 3 ++- test/formal/repeated_or.py | 3 ++- test/formal/replace_mul_by_shift.py | 3 ++- test/formal/rule.py | 2 +- test/formal/shl_workaround_8.py | 3 ++- test/formal/signextend.py | 3 ++- test/formal/signextend_and.py | 3 ++- test/formal/signextend_equivalence.py | 3 ++- test/formal/signextend_shl.py | 3 ++- test/formal/signextend_shr.py | 3 ++- test/formal/sub_not_zero_x_to_not_x_256.py | 3 ++- test/formal/sub_sub.py | 3 ++- test/formal/util.py | 2 +- 36 files changed, 78 insertions(+), 45 deletions(-) diff --git a/test/formal/byte_big.py b/test/formal/byte_big.py index db11bc998..8e6dfd7ef 100644 --- a/test/formal/byte_big.py +++ b/test/formal/byte_big.py @@ -1,5 +1,6 @@ +from opcodes import BYTE from rule import Rule -from opcodes import * +from z3 import BitVec """ byte(A, X) -> 0 diff --git a/test/formal/byte_equivalence.py b/test/formal/byte_equivalence.py index 0f3638424..c607eca4c 100644 --- a/test/formal/byte_equivalence.py +++ b/test/formal/byte_equivalence.py @@ -1,5 +1,6 @@ +from opcodes import BYTE from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal, Concat, Extract """ Checks that the byte opcode (implemented using shift) is equivalent to a diff --git a/test/formal/checked_int_add.py b/test/formal/checked_int_add.py index 6e74944e2..43368a98d 100644 --- a/test/formal/checked_int_add.py +++ b/test/formal/checked_int_add.py @@ -1,6 +1,7 @@ +from opcodes import AND, ISZERO, SGT, SLT, SUB from rule import Rule -from opcodes import * -from util import * +from util import BVSignedMax, BVSignedMin, BVSignedUpCast +from z3 import BitVec, BVAddNoOverflow, BVAddNoUnderflow, Not """ Overflow checked signed integer addition. diff --git a/test/formal/checked_int_div.py b/test/formal/checked_int_div.py index 2a36a9488..4c9d4e829 100644 --- a/test/formal/checked_int_div.py +++ b/test/formal/checked_int_div.py @@ -1,6 +1,7 @@ +from opcodes import AND, EQ, SUB from rule import Rule -from opcodes import * -from util import * +from util import BVSignedMin, BVSignedUpCast +from z3 import BitVec, BVSDivNoOverflow, Not """ Overflow checked signed integer division. diff --git a/test/formal/checked_int_mul_16.py b/test/formal/checked_int_mul_16.py index cc8743b1d..b2f9eb852 100644 --- a/test/formal/checked_int_mul_16.py +++ b/test/formal/checked_int_mul_16.py @@ -1,6 +1,7 @@ +from opcodes import AND, DIV, GT, SDIV, SGT, SLT from rule import Rule -from opcodes import * -from util import * +from util import BVSignedMax, BVSignedMin, BVSignedUpCast +from z3 import BVMulNoOverflow, BVMulNoUnderflow, BitVec, Not, Or """ Overflow checked signed integer multiplication. diff --git a/test/formal/checked_int_sub.py b/test/formal/checked_int_sub.py index 72a0a2109..ed292bbe0 100644 --- a/test/formal/checked_int_sub.py +++ b/test/formal/checked_int_sub.py @@ -1,6 +1,7 @@ +from opcodes import AND, ADD, ISZERO, SLT, SGT from rule import Rule -from opcodes import * -from util import * +from util import BVSignedMax, BVSignedMin, BVSignedUpCast +from z3 import BitVec, BVSubNoOverflow, BVSubNoUnderflow, Not """ Overflow checked signed integer subtraction. diff --git a/test/formal/checked_uint_add.py b/test/formal/checked_uint_add.py index 596fa04f0..e38b4dcdb 100644 --- a/test/formal/checked_uint_add.py +++ b/test/formal/checked_uint_add.py @@ -1,6 +1,7 @@ +from opcodes import GT, SUB from rule import Rule -from opcodes import * -from util import * +from util import BVUnsignedMax, BVUnsignedUpCast +from z3 import BitVec, BVAddNoOverflow, Not """ Overflow checked unsigned integer addition. diff --git a/test/formal/checked_uint_mul_16.py b/test/formal/checked_uint_mul_16.py index 6e8901799..1c60de47b 100644 --- a/test/formal/checked_uint_mul_16.py +++ b/test/formal/checked_uint_mul_16.py @@ -1,6 +1,7 @@ +from opcodes import AND, ISZERO, GT, DIV from rule import Rule -from opcodes import * -from util import * +from util import BVUnsignedUpCast, BVUnsignedMax +from z3 import BitVec, Not, BVMulNoOverflow """ Overflow checked unsigned integer multiplication. diff --git a/test/formal/checked_uint_sub.py b/test/formal/checked_uint_sub.py index b0f25b582..65bcf74a4 100644 --- a/test/formal/checked_uint_sub.py +++ b/test/formal/checked_uint_sub.py @@ -1,6 +1,7 @@ +from opcodes import LT from rule import Rule -from opcodes import * -from util import * +from util import BVUnsignedMax, BVUnsignedUpCast +from z3 import BVSubNoUnderflow, BitVec, Not """ Overflow checked unsigned integer subtraction. diff --git a/test/formal/combine_byte_shl.py b/test/formal/combine_byte_shl.py index e2a6034ff..f492cc18f 100644 --- a/test/formal/combine_byte_shl.py +++ b/test/formal/combine_byte_shl.py @@ -1,5 +1,6 @@ +from opcodes import BYTE, SHL from rule import Rule -from opcodes import * +from z3 import BitVec, ULE """ byte(A, shl(B, X)) diff --git a/test/formal/combine_byte_shr_1.py b/test/formal/combine_byte_shr_1.py index 4938e73f7..788319aa2 100644 --- a/test/formal/combine_byte_shr_1.py +++ b/test/formal/combine_byte_shr_1.py @@ -1,5 +1,6 @@ +from opcodes import BYTE, DIV, SHR from rule import Rule -from opcodes import * +from z3 import BitVec, UGE, ULE, ULT """ byte(A, shr(B, X)) diff --git a/test/formal/combine_byte_shr_2.py b/test/formal/combine_byte_shr_2.py index 4f9be05a4..d969c301b 100644 --- a/test/formal/combine_byte_shr_2.py +++ b/test/formal/combine_byte_shr_2.py @@ -1,5 +1,6 @@ +from opcodes import BYTE, SHR, DIV from rule import Rule -from opcodes import * +from z3 import BitVec, ULT """ byte(A, shr(B, X)) diff --git a/test/formal/combine_div_shl_one_32.py b/test/formal/combine_div_shl_one_32.py index 2ee7d2137..5cca7288b 100644 --- a/test/formal/combine_div_shl_one_32.py +++ b/test/formal/combine_div_shl_one_32.py @@ -1,5 +1,6 @@ +from opcodes import DIV, SHL, SHR from rule import Rule -from opcodes import * +from z3 import BitVec """ Rule: diff --git a/test/formal/combine_mul_shl_one_64.py b/test/formal/combine_mul_shl_one_64.py index 44d031b98..169cc5be0 100644 --- a/test/formal/combine_mul_shl_one_64.py +++ b/test/formal/combine_mul_shl_one_64.py @@ -1,5 +1,6 @@ +from opcodes import SHL, MUL from rule import Rule -from opcodes import * +from z3 import BitVec """ Rule: diff --git a/test/formal/combine_shl_shr_by_constant_64.py b/test/formal/combine_shl_shr_by_constant_64.py index fc7ec64e8..4d8e6a1f8 100644 --- a/test/formal/combine_shl_shr_by_constant_64.py +++ b/test/formal/combine_shl_shr_by_constant_64.py @@ -1,5 +1,6 @@ +from opcodes import AND, SHL, SHR from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal, If, Int2BV, IntVal, UGT, ULT """ Rule: diff --git a/test/formal/combine_shr_shl_by_constant_64.py b/test/formal/combine_shr_shl_by_constant_64.py index c011a2616..5bc852574 100644 --- a/test/formal/combine_shr_shl_by_constant_64.py +++ b/test/formal/combine_shr_shl_by_constant_64.py @@ -1,5 +1,6 @@ +from opcodes import AND, SHL, SHR from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal, If, Int2BV, IntVal, UGT, ULT """ Rule: diff --git a/test/formal/eq_sub.py b/test/formal/eq_sub.py index bf7518acf..76808bc3b 100644 --- a/test/formal/eq_sub.py +++ b/test/formal/eq_sub.py @@ -1,5 +1,6 @@ +from opcodes import EQ, ISZERO, SUB from rule import Rule -from opcodes import * +from z3 import BitVec """ Rule: diff --git a/test/formal/exp_neg_one.py b/test/formal/exp_neg_one.py index 88416496e..4dffb88b0 100644 --- a/test/formal/exp_neg_one.py +++ b/test/formal/exp_neg_one.py @@ -1,6 +1,7 @@ +from opcodes import AND, ISZERO, MOD, SUB from rule import Rule -from opcodes import * -from util import * +from util import BVUnsignedMax +from z3 import BitVec, BitVecVal, If """ Checking conversion of exp(-1, X) to sub(isZero(and(X, 1)), and(X, 1)) diff --git a/test/formal/exp_to_shl.py b/test/formal/exp_to_shl.py index 064d1af3e..499cf7c2f 100644 --- a/test/formal/exp_to_shl.py +++ b/test/formal/exp_to_shl.py @@ -1,6 +1,6 @@ +from opcodes import SHL from rule import Rule -from opcodes import * -from util import * +from z3 import BitVec, If """ Checking conversion of exp(2, X) to shl(X, 1) diff --git a/test/formal/move_and_across_shl_128.py b/test/formal/move_and_across_shl_128.py index d3f5c3a66..9e689b71e 100644 --- a/test/formal/move_and_across_shl_128.py +++ b/test/formal/move_and_across_shl_128.py @@ -1,5 +1,6 @@ +from opcodes import AND, SHL from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal, ULT """ Rule: diff --git a/test/formal/move_and_across_shr_128.py b/test/formal/move_and_across_shr_128.py index 7ec4a65c1..592dc7742 100644 --- a/test/formal/move_and_across_shr_128.py +++ b/test/formal/move_and_across_shr_128.py @@ -1,5 +1,6 @@ +from opcodes import AND, SHR from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal, ULT """ Rule: diff --git a/test/formal/move_and_inside_or.py b/test/formal/move_and_inside_or.py index 09dc35c51..48ec20dba 100644 --- a/test/formal/move_and_inside_or.py +++ b/test/formal/move_and_inside_or.py @@ -1,5 +1,7 @@ +from opcodes import AND, OR from rule import Rule -from opcodes import * +from z3 import BitVec + """ Rule: diff --git a/test/formal/opcodes.py b/test/formal/opcodes.py index 6098d01ed..103e57a14 100644 --- a/test/formal/opcodes.py +++ b/test/formal/opcodes.py @@ -1,4 +1,4 @@ -from z3 import * +from z3 import BitVecVal, BV2Int, If, LShR, UDiv, ULT, UGT, URem def ADD(x, y): return x + y diff --git a/test/formal/repeated_and.py b/test/formal/repeated_and.py index 2e8431b3c..2376ca34f 100644 --- a/test/formal/repeated_and.py +++ b/test/formal/repeated_and.py @@ -1,5 +1,6 @@ +from opcodes import AND from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal """ Rule: diff --git a/test/formal/repeated_or.py b/test/formal/repeated_or.py index c1b2ebd09..ba18e39aa 100644 --- a/test/formal/repeated_or.py +++ b/test/formal/repeated_or.py @@ -1,5 +1,6 @@ +from opcodes import OR from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal """ Rule: diff --git a/test/formal/replace_mul_by_shift.py b/test/formal/replace_mul_by_shift.py index 5a2c2dc14..3805af0dc 100644 --- a/test/formal/replace_mul_by_shift.py +++ b/test/formal/replace_mul_by_shift.py @@ -1,5 +1,6 @@ +from opcodes import DIV, MUL, SHL, SHR from rule import Rule -from opcodes import * +from z3 import BitVec """ Rule: diff --git a/test/formal/rule.py b/test/formal/rule.py index 9327f7e5a..ac0f0c8a6 100644 --- a/test/formal/rule.py +++ b/test/formal/rule.py @@ -1,6 +1,6 @@ import sys -from z3 import * +from z3 import sat, Solver, unknown, unsat class Rule: def __init__(self): diff --git a/test/formal/shl_workaround_8.py b/test/formal/shl_workaround_8.py index 2ca711cdf..19248574a 100644 --- a/test/formal/shl_workaround_8.py +++ b/test/formal/shl_workaround_8.py @@ -1,5 +1,6 @@ +from opcodes import SHL from rule import Rule -from opcodes import * +from z3 import BitVec, BV2Int, Int2BV, IntVal """ Shift left workaround that Solidity implements diff --git a/test/formal/signextend.py b/test/formal/signextend.py index 483fcca56..ed285345d 100644 --- a/test/formal/signextend.py +++ b/test/formal/signextend.py @@ -1,5 +1,6 @@ +from opcodes import SIGNEXTEND from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal, If, UGE, ULT """ Rule: diff --git a/test/formal/signextend_and.py b/test/formal/signextend_and.py index ae2b4bd2c..91fc14349 100644 --- a/test/formal/signextend_and.py +++ b/test/formal/signextend_and.py @@ -1,5 +1,6 @@ +from opcodes import SIGNEXTEND, AND from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal, ULT """ Rule: diff --git a/test/formal/signextend_equivalence.py b/test/formal/signextend_equivalence.py index 1199fff47..3b8386e54 100644 --- a/test/formal/signextend_equivalence.py +++ b/test/formal/signextend_equivalence.py @@ -1,5 +1,6 @@ +from opcodes import SIGNEXTEND from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal, Extract, SignExt, UGT """ Checking the implementation of SIGNEXTEND using Z3's native SignExt and Extract diff --git a/test/formal/signextend_shl.py b/test/formal/signextend_shl.py index 608b10eec..18b1baea1 100644 --- a/test/formal/signextend_shl.py +++ b/test/formal/signextend_shl.py @@ -1,5 +1,6 @@ +from opcodes import SHL, SIGNEXTEND from rule import Rule -from opcodes import * +from z3 import BitVec, LShR, ULE """ Rule: diff --git a/test/formal/signextend_shr.py b/test/formal/signextend_shr.py index aa44a2345..a763314cd 100644 --- a/test/formal/signextend_shr.py +++ b/test/formal/signextend_shr.py @@ -1,5 +1,6 @@ +from opcodes import SIGNEXTEND, SAR, SHR from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal, ULE """ Rule: diff --git a/test/formal/sub_not_zero_x_to_not_x_256.py b/test/formal/sub_not_zero_x_to_not_x_256.py index eb3301100..d8f1282ec 100644 --- a/test/formal/sub_not_zero_x_to_not_x_256.py +++ b/test/formal/sub_not_zero_x_to_not_x_256.py @@ -1,5 +1,6 @@ +from opcodes import NOT, SUB from rule import Rule -from opcodes import * +from z3 import BitVec, BitVecVal """ Rule: diff --git a/test/formal/sub_sub.py b/test/formal/sub_sub.py index d6099c91f..643941085 100644 --- a/test/formal/sub_sub.py +++ b/test/formal/sub_sub.py @@ -1,5 +1,6 @@ +from opcodes import ADD, SUB from rule import Rule -from opcodes import * +from z3 import BitVec """ Rules: diff --git a/test/formal/util.py b/test/formal/util.py index 8331a1fcc..8d0debbef 100644 --- a/test/formal/util.py +++ b/test/formal/util.py @@ -1,4 +1,4 @@ -from z3 import * +from z3 import BitVecVal, Concat, If def BVUnsignedUpCast(x, n_bits): assert x.size() <= n_bits From ac8020d4a76abf9b58fa9688e5b04774e3953c96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 13 Oct 2021 12:26:17 +0200 Subject: [PATCH 44/62] contributing.rst: Tweak details about the location of evmone and hera --- docs/contributing.rst | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 5f3315f1b..ffb1d345c 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -110,19 +110,18 @@ The test system automatically tries to discover the location of the `evmone `_ for running the semantic tests. The ``evmone`` library must be located in the ``deps`` or ``deps/lib`` directory relative to the -current working directory or up to the project root. Alternatively an explicit location -to the ``evmone`` shared object can be specified via the ``ETH_EVMONE`` environment variable. +current working directory, to its parent or its parent's parent. Alternatively an explicit location +for the ``evmone`` shared object can be specified via the ``ETH_EVMONE`` environment variable. -If running semantic tests is not required, the command line -parameter ``--no-semantic-tests`` must be passed to ``./scripts/soltest.sh``. - -The tests that use ``evmone`` are ``libsolidity/semanticTests``, ``libsolidity/GasCosts``, -``libsolidity/SolidityEndToEndTest``. +``evmone`` is needed mainly for running semantic and gas tests. +If you do not have it installed, you can skip these tests by passing the ``--no-semantic-tests`` +flag to ``scripts/soltest.sh``. Running Ewasm tests is disabled by default and can be explicitly enabled via ``./scripts/soltest.sh --ewasm`` and requires `hera `_ to be found by ``soltest``. -The ``hera`` library can is using the same search path as described above for ``evmone``. +The mechanism for locating the ``hera`` library is the same as for ``evmone``, except that the +variable for specifying an explicit location is called ``ETH_HERA``. The ``evmone`` and ``hera`` libraries should both end with the file name extension ``.so`` on Linux, ``.dll`` on Windows systems and ``.dylib`` on macOS. From 95dbbdae2294550f0a99dbdac22bc386d89209f1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 17 Aug 2021 22:50:27 +0200 Subject: [PATCH 45/62] Prepare tests to be meaningful. --- test/cmdlineTests/yul_optimize_runs/input.yul | 2 +- test/cmdlineTests/yul_optimize_runs/output | 7 +++---- test/libyul/yulOptimizerTests/fullSuite/medium.yul | 7 ++++++- .../fullSuite/reuse_vars_bug_in_simplifier.yul | 4 ++-- test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul | 4 ++-- .../yulOptimizerTests/fullSuite/ssaReverseComplex.yul | 4 ++-- test/libyul/yulOptimizerTests/fullSuite/switch_inline.yul | 4 ++-- .../fullSuite/switch_inline_match_default.yul | 4 ++-- 8 files changed, 20 insertions(+), 16 deletions(-) diff --git a/test/cmdlineTests/yul_optimize_runs/input.yul b/test/cmdlineTests/yul_optimize_runs/input.yul index aeb7fd282..07c602a4a 100644 --- a/test/cmdlineTests/yul_optimize_runs/input.yul +++ b/test/cmdlineTests/yul_optimize_runs/input.yul @@ -7,7 +7,7 @@ object "RunsTest1" { object "Runtime" { code { let funcSel := shl(224, 0xabc12345) - mstore(0, funcSel) + sstore(0, funcSel) } } } diff --git a/test/cmdlineTests/yul_optimize_runs/output b/test/cmdlineTests/yul_optimize_runs/output index 20196dcb5..4c98ec30e 100644 --- a/test/cmdlineTests/yul_optimize_runs/output +++ b/test/cmdlineTests/yul_optimize_runs/output @@ -13,7 +13,7 @@ object "RunsTest1" { object "Runtime" { code { { - mstore(0, 0xabc1234500000000000000000000000000000000000000000000000000000000) + sstore(0, 0xabc1234500000000000000000000000000000000000000000000000000000000) } } } @@ -21,7 +21,7 @@ object "RunsTest1" { Binary representation: -602480600d600039806000f3fe7fabc1234500000000000000000000000000000000000000000000000000000000600052 +602480600d600039806000f3fe7fabc1234500000000000000000000000000000000000000000000000000000000600055 Text representation: /* "yul_optimize_runs/input.yul":106:125 */ @@ -47,6 +47,5 @@ sub_0: assembly { /* "yul_optimize_runs/input.yul":277:278 */ 0x00 /* "yul_optimize_runs/input.yul":270:288 */ - mstore + sstore } - diff --git a/test/libyul/yulOptimizerTests/fullSuite/medium.yul b/test/libyul/yulOptimizerTests/fullSuite/medium.yul index 4f1a6f35d..41b77c115 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/medium.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/medium.yul @@ -15,6 +15,8 @@ if sub(2,1) { for { switch mul(1,2) case 2 { mstore(0x40, 0x20) } } sub(1,1) {} { mstore(0x80, 0x40) } } + sstore(0, array_index_access(x, 3)) + sstore(1, mload(0x40)) } // ---- // step: fullSuite @@ -24,7 +26,10 @@ // let p := mload(0x40) // mstore(0x40, add(p, 0x20)) // mstore(0x40, add(p, 96)) -// mstore(add(p, 128), 2) +// let p_1 := add(p, 128) +// mstore(p_1, 2) // mstore(0x40, 0x20) +// sstore(0, p_1) +// sstore(1, 0x20) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/reuse_vars_bug_in_simplifier.yul b/test/libyul/yulOptimizerTests/fullSuite/reuse_vars_bug_in_simplifier.yul index 6e217ae4f..93f2f4ad6 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/reuse_vars_bug_in_simplifier.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/reuse_vars_bug_in_simplifier.yul @@ -6,10 +6,10 @@ function foo() -> x_9 { x_9 := sub(1,sub(x_9,1)) - mstore(sub(1,div(sub(x_9,1),sub(1,sub(x_9,1)))), 1) + sstore(sub(1,div(sub(x_9,1),sub(1,sub(x_9,1)))), 1) } } // ---- // step: fullSuite // -// { { mstore(1, 1) } } +// { { sstore(1, 1) } } diff --git a/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul b/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul index 427c9166b..a7ecc0e46 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul @@ -29,7 +29,7 @@ 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) + sstore(a,b) } // ---- // step: fullSuite @@ -43,7 +43,7 @@ // let a_4, b_4 := abi_decode_bytes_calldata(a_3, b_3) // let a_5, b_5 := abi_decode_bytes_calldata(a_4, b_4) // let a_6, b_6 := abi_decode_bytes_calldata(a_5, b_5) -// mstore(a_6, b_6) +// sstore(a_6, b_6) // } // function abi_decode_bytes_calldata(offset, end) -> arrayPos, length // { diff --git a/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul b/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul index 4421dd3cd..3a061155b 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul @@ -7,7 +7,7 @@ a := mload(b) b := mload(a) } - mstore(a, b) + sstore(a, b) } // ---- // step: fullSuite @@ -21,6 +21,6 @@ // a := mload(mload(mload(b))) // b := mload(a) // } -// mstore(a, b) +// sstore(a, b) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/switch_inline.yul b/test/libyul/yulOptimizerTests/fullSuite/switch_inline.yul index 65c7512d3..1ed995124 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/switch_inline.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/switch_inline.yul @@ -1,5 +1,5 @@ { - mstore(f(1), 0) + sstore(f(1), 0) function f(x) -> y { switch x case 0 { y := 8 } @@ -9,4 +9,4 @@ // ---- // step: fullSuite // -// { { mstore(9, 0) } } +// { { sstore(9, 0) } } diff --git a/test/libyul/yulOptimizerTests/fullSuite/switch_inline_match_default.yul b/test/libyul/yulOptimizerTests/fullSuite/switch_inline_match_default.yul index cff8bd755..6ca3314ab 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/switch_inline_match_default.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/switch_inline_match_default.yul @@ -1,5 +1,5 @@ { - mstore(f(3), 0) + sstore(f(3), 0) function f(x) -> y { switch x case 0 { y := 8 } @@ -10,4 +10,4 @@ // ---- // step: fullSuite // -// { { mstore(10, 0) } } +// { { sstore(10, 0) } } From f1ca8e535b6c1f99082cc81c1214f6052d48f9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 13 Oct 2021 16:34:52 +0200 Subject: [PATCH 46/62] Update the workaround for restore_cache on macOS not to delete files completely --- .circleci/config.yml | 49 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5ed903ac5..ea790cf02 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -160,16 +160,34 @@ defaults: - store_test_results: *store_test_results - store_artifacts: *artifacts_test_results - - steps_restore_cache_homebrew_workaround: &steps_restore_cache_homebrew_workaround + - steps_homebrew_workaround_before_restore_cache: &steps_homebrew_workaround_before_restore_cache steps: - run: - # FIXME: For some reason restore_cache fails saying that it cannot remove the scm/ dir. - # The directory contains only two files: `git` (wrapper script over git) and `svn` (symlink - # to `git`). This looks like a bug in restore_cache. Removing scm/ is a workaround. + # Homebrew has recently replaced one of its dirs with a symlink to another. + # This makes tar used by restore_cache fail - the image contains an older version of + # Homebrew installed where it's a directory and tar refuses to overwrite a dir with a link. + # Removing the directory manually is a workaround that works only in case we do have + # cached files to restore. If we don't, we still need this dir because it contains + # a git wrapper that Homebrew uses to update itself. The solution is to just rename the + # dir before restore_cache and renamed it back afterwards. # See https://github.com/ethereum/solidity/pull/12106 for more details. name: Workaround for restore_cache + /usr/local/Homebrew/Library/Homebrew/shims/scm/ command: | - rm -r /usr/local/Homebrew/Library/Homebrew/shims/scm/ + cd /usr/local/Homebrew/Library/Homebrew/shims/ + mv scm/ scm-backup/ + + - steps_homebrew_workaround_after_restore_cache: &steps_homebrew_workaround_after_restore_cache + steps: + - run: + name: Workaround for restore_cache + /usr/local/Homebrew/Library/Homebrew/shims/scm/ + command: | + cd /usr/local/Homebrew/Library/Homebrew/shims/ + if ! [[ -e scm/ ]] + then + mv scm-backup/ scm/ + else + rm -r scm-backup/ + fi - test_ubuntu1604_clang: &test_ubuntu1604_clang docker: @@ -638,12 +656,17 @@ jobs: - checkout - when: condition: true - <<: *steps_restore_cache_homebrew_workaround + # FIXME: Remove this workaround when CircleCI fixes restore_cache. + <<: *steps_homebrew_workaround_before_restore_cache - restore_cache: keys: - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} # DO NOT EDIT between here and save_cache, but rather edit ./circleci/osx_install_dependencies.sh # WARNING! If you do edit anything here instead, remember to invalidate the cache manually. + - when: + condition: true + # FIXME: Remove this workaround when CircleCI fixes restore_cache. + <<: *steps_homebrew_workaround_after_restore_cache - run: name: Install build dependencies command: ./.circleci/osx_install_dependencies.sh @@ -677,10 +700,15 @@ jobs: - checkout - when: condition: true - <<: *steps_restore_cache_homebrew_workaround + # FIXME: Remove this workaround when CircleCI fixes restore_cache. + <<: *steps_homebrew_workaround_before_restore_cache - restore_cache: keys: - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} + - when: + condition: true + # FIXME: Remove this workaround when CircleCI fixes restore_cache. + <<: *steps_homebrew_workaround_after_restore_cache - attach_workspace: at: . - run: *run_soltest @@ -696,10 +724,15 @@ jobs: - checkout - when: condition: true - <<: *steps_restore_cache_homebrew_workaround + # FIXME: Remove this workaround when CircleCI fixes restore_cache. + <<: *steps_homebrew_workaround_before_restore_cache - restore_cache: keys: - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} + - when: + condition: true + # FIXME: Remove this workaround when CircleCI fixes restore_cache. + <<: *steps_homebrew_workaround_after_restore_cache - attach_workspace: at: . - run: *run_cmdline_tests From ed722700cdb9f806d5991f007a256477ef2aa2fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 14 Oct 2021 14:05:14 +0200 Subject: [PATCH 47/62] docs: Put the index menu item into a list prevent it from being styled as unfolded --- docs/_templates/layout.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html index 41713a109..498c0e6e9 100644 --- a/docs/_templates/layout.html +++ b/docs/_templates/layout.html @@ -2,5 +2,9 @@ {% block menu %} {{ super() }} - Keyword Index + {% endblock %} From 6aa9633a024d94566e6d2ce44a94a49d1f0eba02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 14 Oct 2021 14:06:02 +0200 Subject: [PATCH 48/62] docs: Add more bottom padding to the menu to prevent the index link from being obscured by the toggle --- docs/_static/css/toggle.css | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/_static/css/toggle.css b/docs/_static/css/toggle.css index ebbd0658a..add134f6c 100644 --- a/docs/_static/css/toggle.css +++ b/docs/_static/css/toggle.css @@ -74,4 +74,10 @@ html.transition *:before, html.transition *:after { transition: ease-in-out 200ms !important; transition-delay: 0 !important; -} \ No newline at end of file +} + +nav.wy-nav-side { + /* The default padding of 2em is too small and the "Keyword Index" link gets obscured + * by the version toggle. */ + padding-bottom: 3em; +} From ac64ae56a136ba516eb849d4d49f3b67c2fd95d0 Mon Sep 17 00:00:00 2001 From: MrBrain295 <66077254+MrBrain295@users.noreply.github.com> Date: Tue, 12 Oct 2021 16:57:45 -0500 Subject: [PATCH 49/62] Minor rewording. --- docs/examples/micropayment.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index b1d963ee5..3383e6195 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -11,7 +11,7 @@ sign and verify signatures, and setup the payment channel. Creating and verifying signatures ================================= -Imagine Alice wants to send a quantity of Ether to Bob, i.e. +Imagine Alice wants to send some Ether to Bob, i.e. Alice is the sender and Bob is the recipient. Alice only needs to send cryptographically signed messages off-chain From 86a7e1987919f8d1ba931fa93a337f8aea288021 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 24 Mar 2021 12:49:55 +0100 Subject: [PATCH 50/62] libsolidity: Adding a comment to nameLocation(). --- libsolidity/ast/AST.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index c229252a8..b7d5db805 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -246,7 +246,10 @@ public: /// @returns the declared name. ASTString const& name() const { return *m_name; } + + /// @returns the location of the declared name itself or empty location if not available or unknown. SourceLocation const& nameLocation() const noexcept { return m_nameLocation; } + bool noVisibilitySpecified() const { return m_visibility == Visibility::Default; } Visibility visibility() const { return m_visibility == Visibility::Default ? defaultVisibility() : m_visibility; } bool isPublic() const { return visibility() >= Visibility::Public; } From 35a81073b822545b33c09f570694b2e41c7c7a18 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 24 Mar 2021 12:48:56 +0100 Subject: [PATCH 51/62] liblangutil: Adds a convenience helper method SourceLocation::contains(int _pos). --- liblangutil/SourceLocation.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/liblangutil/SourceLocation.h b/liblangutil/SourceLocation.h index 66cef52fb..ea9958933 100644 --- a/liblangutil/SourceLocation.h +++ b/liblangutil/SourceLocation.h @@ -59,6 +59,13 @@ struct SourceLocation return start <= _other.start && _other.end <= end; } + bool containsOffset(int _pos) const + { + if (!hasText() || _pos < 0) + return false; + return start <= _pos && _pos < end; + } + bool intersects(SourceLocation const& _other) const { if (!hasText() || !_other.hasText() || !equalSources(_other)) From 9417d6775f25da81cdd57ff59a0ea05be16e6a97 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 30 Sep 2021 17:01:54 +0200 Subject: [PATCH 52/62] Control flow side-effects for user-defined functions. --- libsolidity/analysis/ControlFlowBuilder.cpp | 14 +- libyul/CMakeLists.txt | 3 + libyul/ControlFlowSideEffects.h | 28 +- libyul/ControlFlowSideEffectsCollector.cpp | 274 ++++++++++++++++++ libyul/ControlFlowSideEffectsCollector.h | 130 +++++++++ libyul/Dialect.h | 2 +- libyul/SideEffects.h | 2 +- .../backends/evm/ControlFlowGraphBuilder.cpp | 2 +- libyul/backends/evm/EVMDialect.cpp | 16 +- .../evm/OptimizedEVMCodeTransform.cpp | 2 +- libyul/backends/wasm/WasmDialect.cpp | 13 +- .../optimiser/FunctionDefinitionCollector.cpp | 2 +- .../optimiser/FunctionDefinitionCollector.h | 2 +- test/CMakeLists.txt | 2 + test/InteractiveTests.h | 6 +- test/libyul/ControlFlowSideEffectsTest.cpp | 79 +++++ test/libyul/ControlFlowSideEffectsTest.h | 40 +++ .../simple_conditionals.yul | 34 +++ .../simple_functions.yul | 17 ++ test/tools/CMakeLists.txt | 1 + 20 files changed, 637 insertions(+), 32 deletions(-) create mode 100644 libyul/ControlFlowSideEffectsCollector.cpp create mode 100644 libyul/ControlFlowSideEffectsCollector.h create mode 100644 test/libyul/ControlFlowSideEffectsTest.cpp create mode 100644 test/libyul/ControlFlowSideEffectsTest.h create mode 100644 test/libyul/controlFlowSideEffects/simple_conditionals.yul create mode 100644 test/libyul/controlFlowSideEffects/simple_functions.yul diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index 2d03aaf9c..ff8e2a29a 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -533,14 +533,14 @@ void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall) yul::ASTWalker::operator()(_functionCall); if (auto const *builtinFunction = m_inlineAssembly->dialect().builtin(_functionCall.functionName.name)) - if (builtinFunction->controlFlowSideEffects.terminates) - { - if (builtinFunction->controlFlowSideEffects.reverts) - connect(m_currentNode, m_revertNode); - else - connect(m_currentNode, m_transactionReturnNode); + { + if (builtinFunction->controlFlowSideEffects.canTerminate) + connect(m_currentNode, m_transactionReturnNode); + if (builtinFunction->controlFlowSideEffects.canRevert) + connect(m_currentNode, m_revertNode); + if (!builtinFunction->controlFlowSideEffects.canContinue) m_currentNode = newLabel(); - } + } } void ControlFlowBuilder::operator()(yul::FunctionDefinition const&) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 0ddb9c64a..30b97b5f7 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -34,6 +34,9 @@ add_library(yul AssemblyStack.cpp CompilabilityChecker.cpp CompilabilityChecker.h + ControlFlowSideEffects.h + ControlFlowSideEffectsCollector.cpp + ControlFlowSideEffectsCollector.h Dialect.cpp Dialect.h Exceptions.h diff --git a/libyul/ControlFlowSideEffects.h b/libyul/ControlFlowSideEffects.h index 5e22ad862..d4debab93 100644 --- a/libyul/ControlFlowSideEffects.h +++ b/libyul/ControlFlowSideEffects.h @@ -18,22 +18,32 @@ #pragma once -#include - namespace solidity::yul { /** - * Side effects of code related to control flow. + * Side effects of a user-defined or builtin function. + * + * Each of the three booleans represents a reachability condition. There is an implied + * fourth alternative, which is going out of gas while executing the function. Since + * this can always happen and depends on the supply of gas, it is not considered. + * + * If all three booleans are false, it means that the function always leads to infinite + * recursion. */ struct ControlFlowSideEffects { - /// If true, this code terminates the control flow. - /// State may or may not be reverted as indicated by the ``reverts`` flag. - bool terminates = false; - /// If true, this code reverts all state changes in the transaction. - /// Whenever this is true, ``terminates`` has to be true as well. - bool reverts = false; + /// If true, the function contains at least one reachable branch that terminates successfully. + bool canTerminate = false; + /// If true, the function contains at least one reachable branch that reverts. + bool canRevert = false; + /// If true, the function has a regular outgoing control-flow. + bool canContinue = true; + + bool terminatesOrReverts() const + { + return (canTerminate || canRevert) && !canContinue; + } }; } diff --git a/libyul/ControlFlowSideEffectsCollector.cpp b/libyul/ControlFlowSideEffectsCollector.cpp new file mode 100644 index 000000000..047480f14 --- /dev/null +++ b/libyul/ControlFlowSideEffectsCollector.cpp @@ -0,0 +1,274 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +using namespace std; +using namespace solidity::yul; + + +ControlFlowBuilder::ControlFlowBuilder(Block const& _ast) +{ + for (auto const& statement: _ast.statements) + if (auto const* function = get_if(&statement)) + (*this)(*function); +} + +void ControlFlowBuilder::operator()(FunctionCall const& _functionCall) +{ + walkVector(_functionCall.arguments | ranges::views::reverse); + newConnectedNode(); + m_currentNode->functionCall = _functionCall.functionName.name; +} + +void ControlFlowBuilder::operator()(If const& _if) +{ + visit(*_if.condition); + ControlFlowNode* node = m_currentNode; + (*this)(_if.body); + newConnectedNode(); + node->successors.emplace_back(m_currentNode); +} + +void ControlFlowBuilder::operator()(Switch const& _switch) +{ + visit(*_switch.expression); + ControlFlowNode* initialNode = m_currentNode; + ControlFlowNode* finalNode = newNode(); + + if (_switch.cases.back().value) + initialNode->successors.emplace_back(finalNode); + + for (Case const& case_: _switch.cases) + { + m_currentNode = initialNode; + (*this)(case_.body); + newConnectedNode(); + m_currentNode->successors.emplace_back(finalNode); + } + m_currentNode = finalNode; +} + +void ControlFlowBuilder::operator()(FunctionDefinition const& _function) +{ + ScopedSaveAndRestore currentNode(m_currentNode, nullptr); + yulAssert(!m_leave && !m_break && !m_continue, "Function hoister has not been used."); + + FunctionFlow flow; + flow.exit = newNode(); + m_currentNode = newNode(); + flow.entry = m_currentNode; + m_leave = flow.exit; + + (*this)(_function.body); + + m_currentNode->successors.emplace_back(flow.exit); + + m_functionFlows[_function.name] = move(flow); + + m_leave = nullptr; +} + +void ControlFlowBuilder::operator()(ForLoop const& _for) +{ + ScopedSaveAndRestore scopedBreakNode(m_break, nullptr); + ScopedSaveAndRestore scopedContinueNode(m_continue, nullptr); + + (*this)(_for.pre); + + ControlFlowNode* breakNode = newNode(); + m_break = breakNode; + ControlFlowNode* continueNode = newNode(); + m_continue = continueNode; + + newConnectedNode(); + ControlFlowNode* loopNode = m_currentNode; + visit(*_for.condition); + m_currentNode->successors.emplace_back(m_break); + newConnectedNode(); + + (*this)(_for.body); + + m_currentNode->successors.emplace_back(m_continue); + m_currentNode = continueNode; + + (*this)(_for.post); + m_currentNode->successors.emplace_back(loopNode); + + m_currentNode = breakNode; +} + +void ControlFlowBuilder::operator()(Break const&) +{ + yulAssert(m_break); + m_currentNode->successors.emplace_back(m_break); + m_currentNode = newNode(); +} + +void ControlFlowBuilder::operator()(Continue const&) +{ + yulAssert(m_continue); + m_currentNode->successors.emplace_back(m_continue); + m_currentNode = newNode(); +} + +void ControlFlowBuilder::operator()(Leave const&) +{ + yulAssert(m_leave); + m_currentNode->successors.emplace_back(m_leave); + m_currentNode = newNode(); +} + +void ControlFlowBuilder::newConnectedNode() +{ + ControlFlowNode* node = newNode(); + m_currentNode->successors.emplace_back(node); + m_currentNode = node; +} + +ControlFlowNode* ControlFlowBuilder::newNode() +{ + m_nodes.emplace_back(make_shared()); + return m_nodes.back().get(); +} + + +ControlFlowSideEffectsCollector::ControlFlowSideEffectsCollector( + Dialect const& _dialect, + Block const& _ast +): + m_dialect(_dialect), + m_cfgBuilder(_ast) +{ + for (auto&& [name, flow]: m_cfgBuilder.functionFlows()) + { + yulAssert(!flow.entry->functionCall); + m_processedNodes[name] = {}; + m_pendingNodes[name].push_front(flow.entry); + m_functionSideEffects[name] = {false, false, false}; + } + + // Process functions while we have progress. For now, we are only interested + // in `canContinue`. + bool progress = true; + while (progress) + { + progress = false; + for (auto const& functionName: m_pendingNodes | ranges::views::keys) + if (processFunction(functionName)) + progress = true; + } + + // No progress anymore: All remaining nodes are calls + // to functions that always recurse. + // If we have not set `canContinue` by now, the function's exit + // is not reachable. + + for (auto&& [functionName, calls]: m_functionCalls) + { + ControlFlowSideEffects& sideEffects = m_functionSideEffects[functionName]; + auto _visit = [&, visited = std::set{}](YulString _function, auto&& _recurse) mutable { + if (sideEffects.canTerminate && sideEffects.canRevert) + return; + if (!visited.insert(_function).second) + return; + + ControlFlowSideEffects const* calledSideEffects = nullptr; + if (BuiltinFunction const* f = _dialect.builtin(_function)) + calledSideEffects = &f->controlFlowSideEffects; + else + calledSideEffects = &m_functionSideEffects.at(_function); + + if (calledSideEffects->canTerminate) + sideEffects.canTerminate = true; + if (calledSideEffects->canRevert) + sideEffects.canRevert = true; + + for (YulString callee: util::valueOrDefault(m_functionCalls, _function)) + _recurse(callee, _recurse); + }; + for (auto const& call: calls) + _visit(call, _visit); + } + +} + +bool ControlFlowSideEffectsCollector::processFunction(YulString _name) +{ + bool progress = false; + while (ControlFlowNode const* node = nextProcessableNode(_name)) + { + if (node == m_cfgBuilder.functionFlows().at(_name).exit) + { + m_functionSideEffects[_name].canContinue = true; + return true; + } + for (ControlFlowNode const* s: node->successors) + recordReachabilityAndQueue(_name, s); + + progress = true; + } + return progress; +} + +ControlFlowNode const* ControlFlowSideEffectsCollector::nextProcessableNode(YulString _functionName) +{ + std::list& nodes = m_pendingNodes[_functionName]; + auto it = ranges::find_if(nodes, [this](ControlFlowNode const* _node) { + return !_node->functionCall || sideEffects(*_node->functionCall).canContinue; + }); + if (it == nodes.end()) + return nullptr; + + ControlFlowNode const* node = *it; + nodes.erase(it); + return node; +} + +ControlFlowSideEffects const& ControlFlowSideEffectsCollector::sideEffects(YulString _functionName) const +{ + if (auto const* builtin = m_dialect.builtin(_functionName)) + return builtin->controlFlowSideEffects; + else + return m_functionSideEffects.at(_functionName); +} + +void ControlFlowSideEffectsCollector::recordReachabilityAndQueue( + YulString _functionName, + ControlFlowNode const* _node +) +{ + if (_node->functionCall) + m_functionCalls[_functionName].insert(*_node->functionCall); + if (m_processedNodes[_functionName].insert(_node).second) + m_pendingNodes.at(_functionName).push_front(_node); +} + diff --git a/libyul/ControlFlowSideEffectsCollector.h b/libyul/ControlFlowSideEffectsCollector.h new file mode 100644 index 000000000..f130294ba --- /dev/null +++ b/libyul/ControlFlowSideEffectsCollector.h @@ -0,0 +1,130 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace solidity::yul +{ + +struct Dialect; + +struct ControlFlowNode +{ + std::vector successors; + /// Name of the called function if the node calls a function. + std::optional functionCall; +}; + +/** + * The control flow of a function with entry and exit nodes. + */ +struct FunctionFlow +{ + ControlFlowNode const* entry; + ControlFlowNode const* exit; +}; + +/** + * Requires: Disambiguator, Function Hoister. + */ +class ControlFlowBuilder: private ASTWalker +{ +public: + /// Computes the control-flows of all function defined in the block. + /// Assumes the functions are hoisted to the topmost block. + explicit ControlFlowBuilder(Block const& _ast); + std::map const& functionFlows() const { return m_functionFlows; } + +private: + using ASTWalker::operator(); + void operator()(FunctionCall const& _functionCall) override; + void operator()(If const& _if) override; + void operator()(Switch const& _switch) override; + void operator()(FunctionDefinition const& _functionDefinition) override; + void operator()(ForLoop const& _forLoop) override; + void operator()(Break const& _break) override; + void operator()(Continue const& _continue) override; + void operator()(Leave const& _leaveStatement) override; + + void newConnectedNode(); + ControlFlowNode* newNode(); + + std::vector> m_nodes; + + ControlFlowNode* m_currentNode = nullptr; + ControlFlowNode const* m_leave = nullptr; + ControlFlowNode const* m_break = nullptr; + ControlFlowNode const* m_continue = nullptr; + + std::map m_functionFlows; +}; + + +/** + * Requires: Disambiguator, Function Hoister. + */ +class ControlFlowSideEffectsCollector +{ +public: + explicit ControlFlowSideEffectsCollector( + Dialect const& _dialect, + Block const& _ast + ); + + std::map const& functionSideEffects() const + { + return m_functionSideEffects; + } +private: + + /// @returns false if nothing could be processed. + bool processFunction(YulString _name); + + /// @returns the next pending node of the function that is not + /// a function call to a function that might not continue. + /// De-queues the node or returns nullptr if no such node is found. + ControlFlowNode const* nextProcessableNode(YulString _functionName); + + /// @returns the side-effects of either a builtin call or a user defined function + /// call (as far as already computed). + ControlFlowSideEffects const& sideEffects(YulString _functionName) const; + + /// Queues the given node to be processed (if not already visited) + /// and if it is a function call, records that `_functionName` calls + /// `*_node->functionCall`. + void recordReachabilityAndQueue(YulString _functionName, ControlFlowNode const* _node); + + Dialect const& m_dialect; + ControlFlowBuilder m_cfgBuilder; + std::map m_functionSideEffects; + std::map> m_pendingNodes; + std::map> m_processedNodes; + /// `x` is in `m_functionCalls[y]` if a direct call to `x` is reachable inside `y` + std::map> m_functionCalls; +}; + + +} diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 87deb04b9..e7a5e4827 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -22,8 +22,8 @@ #pragma once #include -#include #include +#include #include #include diff --git a/libyul/SideEffects.h b/libyul/SideEffects.h index 7433e40d2..b6df8df83 100644 --- a/libyul/SideEffects.h +++ b/libyul/SideEffects.h @@ -94,7 +94,7 @@ struct SideEffects cannotLoop && _other.cannotLoop, otherState + _other.otherState, storage + _other.storage, - memory + _other.memory + memory + _other.memory }; } diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 2c61bfb89..7e57b8257 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -229,7 +229,7 @@ void ControlFlowGraphBuilder::operator()(ExpressionStatement const& _exprStmt) // not only for builtins. if (auto const* funCall = get_if(&_exprStmt.expression)) if (BuiltinFunction const* builtin = m_dialect.builtin(funCall->functionName.name)) - if (builtin->controlFlowSideEffects.terminates) + if (builtin->controlFlowSideEffects.terminatesOrReverts()) { m_currentBlock->exit = CFG::BasicBlock::Terminated{}; m_currentBlock = &m_graph.makeBlock(debugDataOf(*m_currentBlock)); diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index c90784a03..0fefb24d0 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -57,8 +57,20 @@ pair createEVMFunction( f.parameters.resize(static_cast(info.args)); f.returns.resize(static_cast(info.ret)); f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); - f.controlFlowSideEffects.terminates = evmasm::SemanticInformation::terminatesControlFlow(_instruction); - f.controlFlowSideEffects.reverts = evmasm::SemanticInformation::reverts(_instruction); + if (evmasm::SemanticInformation::terminatesControlFlow(_instruction)) + { + f.controlFlowSideEffects.canContinue = false; + if (evmasm::SemanticInformation::reverts(_instruction)) + { + f.controlFlowSideEffects.canTerminate = false; + f.controlFlowSideEffects.canRevert = true; + } + else + { + f.controlFlowSideEffects.canTerminate = true; + f.controlFlowSideEffects.canRevert = false; + } + } f.isMSize = _instruction == evmasm::Instruction::MSIZE; f.literalArguments.clear(); f.instruction = _instruction; diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 106e636c8..ca57c59d2 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -484,7 +484,7 @@ void OptimizedEVMCodeTransform::operator()(CFG::BasicBlock const& _block) yulAssert(!_block.operations.empty(), ""); CFG::BuiltinCall const* builtinCall = get_if(&_block.operations.back().operation); yulAssert(builtinCall, ""); - yulAssert(builtinCall->builtin.get().controlFlowSideEffects.terminates, ""); + yulAssert(builtinCall->builtin.get().controlFlowSideEffects.terminatesOrReverts(), ""); } }, _block.exit); // TODO: We could assert that the last emitted assembly item terminated or was an (unconditional) jump. diff --git a/libyul/backends/wasm/WasmDialect.cpp b/libyul/backends/wasm/WasmDialect.cpp index faaf366c1..817d53467 100644 --- a/libyul/backends/wasm/WasmDialect.cpp +++ b/libyul/backends/wasm/WasmDialect.cpp @@ -129,8 +129,9 @@ WasmDialect::WasmDialect() m_functions["unreachable"_yulstring].sideEffects.storage = SideEffects::None; m_functions["unreachable"_yulstring].sideEffects.memory = SideEffects::None; m_functions["unreachable"_yulstring].sideEffects.otherState = SideEffects::None; - m_functions["unreachable"_yulstring].controlFlowSideEffects.terminates = true; - m_functions["unreachable"_yulstring].controlFlowSideEffects.reverts = true; + m_functions["unreachable"_yulstring].controlFlowSideEffects.canTerminate = false; + m_functions["unreachable"_yulstring].controlFlowSideEffects.canRevert = true; + m_functions["unreachable"_yulstring].controlFlowSideEffects.canContinue = false; addFunction("datasize", {i64}, {i64}, true, {LiteralKind::String}); addFunction("dataoffset", {i64}, {i64}, true, {LiteralKind::String}); @@ -215,11 +216,11 @@ void WasmDialect::addExternals() {"eth", "log", {i32ptr, i32, i32, i32ptr, i32ptr, i32ptr, i32ptr}, {}}, {"eth", "getBlockNumber", {}, {i64}}, {"eth", "getTxOrigin", {i32ptr}, {}}, - {"eth", "finish", {i32ptr, i32}, {}, ControlFlowSideEffects{true, false}}, - {"eth", "revert", {i32ptr, i32}, {}, ControlFlowSideEffects{true, true}}, + {"eth", "finish", {i32ptr, i32}, {}, ControlFlowSideEffects{true, false, false}}, + {"eth", "revert", {i32ptr, i32}, {}, ControlFlowSideEffects{false, true, false}}, {"eth", "getReturnDataSize", {}, {i32}}, {"eth", "returnDataCopy", {i32ptr, i32, i32}, {}}, - {"eth", "selfDestruct", {i32ptr}, {}, ControlFlowSideEffects{true, false}}, + {"eth", "selfDestruct", {i32ptr}, {}, ControlFlowSideEffects{false, true, false}}, {"eth", "getBlockTimestamp", {}, {i64}}, {"debug", "print32", {i32}, {}}, {"debug", "print64", {i64}, {}}, @@ -240,7 +241,7 @@ void WasmDialect::addExternals() // TODO some of them are side effect free. f.sideEffects = SideEffects::worst(); f.sideEffects.cannotLoop = true; - f.sideEffects.movableApartFromEffects = !ext.controlFlowSideEffects.terminates; + f.sideEffects.movableApartFromEffects = !ext.controlFlowSideEffects.terminatesOrReverts(); f.controlFlowSideEffects = ext.controlFlowSideEffects; f.isMSize = false; f.literalArguments.clear(); diff --git a/libyul/optimiser/FunctionDefinitionCollector.cpp b/libyul/optimiser/FunctionDefinitionCollector.cpp index 70f2a268d..dff57a32a 100644 --- a/libyul/optimiser/FunctionDefinitionCollector.cpp +++ b/libyul/optimiser/FunctionDefinitionCollector.cpp @@ -22,7 +22,7 @@ using namespace std; using namespace solidity; using namespace solidity::yul; -map FunctionDefinitionCollector::run(Block& _block) +map FunctionDefinitionCollector::run(Block const& _block) { FunctionDefinitionCollector functionDefinitionCollector; functionDefinitionCollector(_block); diff --git a/libyul/optimiser/FunctionDefinitionCollector.h b/libyul/optimiser/FunctionDefinitionCollector.h index c97f20d67..c9828aced 100644 --- a/libyul/optimiser/FunctionDefinitionCollector.h +++ b/libyul/optimiser/FunctionDefinitionCollector.h @@ -34,7 +34,7 @@ namespace solidity::yul class FunctionDefinitionCollector: ASTWalker { public: - static std::map run(Block& _block); + static std::map run(Block const& _block); private: using ASTWalker::operator(); void operator()(FunctionDefinition const& _functionDefinition) override; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3135b53d5..3a0b5f7b6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -130,6 +130,8 @@ set(libyul_sources libyul/CompilabilityChecker.cpp libyul/ControlFlowGraphTest.cpp libyul/ControlFlowGraphTest.h + libyul/ControlFlowSideEffectsTest.cpp + libyul/ControlFlowSideEffectsTest.h libyul/EVMCodeTransformTest.cpp libyul/EVMCodeTransformTest.h libyul/EwasmTranslationTest.cpp diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index e27c00b84..d8f3ef07e 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -57,12 +58,12 @@ struct Testsuite Testsuite const g_interactiveTestsuites[] = { /* Title Path Subpath SMT NeedsVM Creator function */ - {"Ewasm Translation", "libyul", "ewasmTranslationTests", false, false, &yul::test::EwasmTranslationTest::create}, {"Yul Optimizer", "libyul", "yulOptimizerTests", false, false, &yul::test::YulOptimizerTest::create}, {"Yul Interpreter", "libyul", "yulInterpreterTests", false, false, &yul::test::YulInterpreterTest::create}, {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, {"Yul Control Flow Graph", "libyul", "yulControlFlowGraph", false, false, &yul::test::ControlFlowGraphTest::create}, {"Yul Stack Layout", "libyul", "yulStackLayout", false, false, &yul::test::StackLayoutGeneratorTest::create}, + {"Control Flow Side Effects","libyul", "controlFlowSideEffects",false, false, &yul::test::ControlFlowSideEffectsTest::create}, {"Function Side Effects", "libyul", "functionSideEffects", false, false, &yul::test::FunctionSideEffects::create}, {"Yul Syntax", "libyul", "yulSyntaxTests", false, false, &yul::test::SyntaxTest::create}, {"EVM Code Transform", "libyul", "evmCodeTransform", false, false, &yul::test::EVMCodeTransformTest::create, {"nooptions"}}, @@ -72,7 +73,8 @@ Testsuite const g_interactiveTestsuites[] = { {"JSON AST", "libsolidity", "ASTJSON", false, false, &ASTJSONTest::create}, {"JSON ABI", "libsolidity", "ABIJson", false, false, &ABIJsonTest::create}, {"SMT Checker", "libsolidity", "smtCheckerTests", true, false, &SMTCheckerTest::create}, - {"Gas Estimates", "libsolidity", "gasTests", false, false, &GasTest::create} + {"Gas Estimates", "libsolidity", "gasTests", false, false, &GasTest::create}, + {"Ewasm Translation", "libyul", "ewasmTranslationTests", false, false, &yul::test::EwasmTranslationTest::create} }; } diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp new file mode 100644 index 000000000..aff3c564d --- /dev/null +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -0,0 +1,79 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace std; +using namespace solidity; +using namespace solidity::yul; +using namespace solidity::yul::test; +using namespace solidity::frontend::test; + +namespace +{ +string toString(ControlFlowSideEffects const& _sideEffects) +{ + vector r; + if (_sideEffects.canTerminate) + r.emplace_back("can terminate"); + if (_sideEffects.canRevert) + r.emplace_back("can revert"); + if (_sideEffects.canContinue) + r.emplace_back("can continue"); + return util::joinHumanReadable(r); +} +} + +ControlFlowSideEffectsTest::ControlFlowSideEffectsTest(string const& _filename): + TestCase(_filename) +{ + m_source = m_reader.source(); + m_expectation = m_reader.simpleExpectations(); +} + +TestCase::TestResult ControlFlowSideEffectsTest::run(ostream& _stream, string const& _linePrefix, bool _formatted) +{ + Object obj; + std::tie(obj.code, obj.analysisInfo) = yul::test::parse(m_source, false); + if (!obj.code) + BOOST_THROW_EXCEPTION(runtime_error("Parsing input failed.")); + + std::map sideEffects = + ControlFlowSideEffectsCollector( + EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + *obj.code + ).functionSideEffects(); + + std::map controlFlowSideEffectsStr; + for (auto&& [fun, effects]: sideEffects) + controlFlowSideEffectsStr[fun.str()] = toString(effects); + + m_obtainedResult.clear(); + for (auto&& [functionName, effect]: controlFlowSideEffectsStr) + m_obtainedResult += functionName + (effect.empty() ? ":" : ": " + effect) + "\n"; + + return checkResult(_stream, _linePrefix, _formatted); +} diff --git a/test/libyul/ControlFlowSideEffectsTest.h b/test/libyul/ControlFlowSideEffectsTest.h new file mode 100644 index 000000000..f91378e55 --- /dev/null +++ b/test/libyul/ControlFlowSideEffectsTest.h @@ -0,0 +1,40 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#pragma once + +#include + +#include +#include +#include +#include + +namespace solidity::yul::test +{ + +class ControlFlowSideEffectsTest: public solidity::frontend::test::TestCase +{ +public: + static std::unique_ptr create(Config const& _config) + { return std::make_unique(_config.filename); } + explicit ControlFlowSideEffectsTest(std::string const& _filename); + TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; +}; + +} diff --git a/test/libyul/controlFlowSideEffects/simple_conditionals.yul b/test/libyul/controlFlowSideEffects/simple_conditionals.yul new file mode 100644 index 000000000..ec15193df --- /dev/null +++ b/test/libyul/controlFlowSideEffects/simple_conditionals.yul @@ -0,0 +1,34 @@ +{ + function a() { + if calldataload(0) { g() } + } + function b() { + g() + if calldataload(0) { } + } + function c() { + if calldataload(0) { } + g() + } + function d() { + stop() + if calldataload(0) { g() } + } + function e() { + if calldataload(0) { g() } + stop() + } + function f() { + g() + if calldataload(0) { g() } + } + function g() { revert(0, 0) } +} +// ---- +// a: can revert, can continue +// b: can revert +// c: can revert +// d: can terminate +// e: can terminate, can revert +// f: can revert +// g: can revert diff --git a/test/libyul/controlFlowSideEffects/simple_functions.yul b/test/libyul/controlFlowSideEffects/simple_functions.yul new file mode 100644 index 000000000..b6b14d39d --- /dev/null +++ b/test/libyul/controlFlowSideEffects/simple_functions.yul @@ -0,0 +1,17 @@ +{ + function a() {} + function f() { g() } + function g() { revert(0, 0) } + function h() { stop() } + function i() { h() } + function j() { h() g() } + function k() { g() h() } +} +// ---- +// a: can continue +// f: can revert +// g: can revert +// h: can terminate +// i: can terminate +// j: can terminate +// k: can revert diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 18b04afe8..18e3d4377 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -33,6 +33,7 @@ add_executable(isoltest ../libsolidity/SMTCheckerTest.cpp ../libyul/Common.cpp ../libyul/ControlFlowGraphTest.cpp + ../libyul/ControlFlowSideEffectsTest.cpp ../libyul/EVMCodeTransformTest.cpp ../libyul/EwasmTranslationTest.cpp ../libyul/FunctionSideEffects.cpp From 2c2269d30024f7859e40ab400863a3829424059f Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 4 Oct 2021 18:09:08 +0200 Subject: [PATCH 53/62] Tests --- .../controlFlowSideEffects/eval_order.yul | 19 +++++++ .../controlFlowSideEffects/for_loop.yul | 55 +++++++++++++++++++ test/libyul/controlFlowSideEffects/leave.yul | 13 +++++ .../controlFlowSideEffects/recursion.yul | 37 +++++++++++++ test/libyul/controlFlowSideEffects/switch.yul | 41 ++++++++++++++ 5 files changed, 165 insertions(+) create mode 100644 test/libyul/controlFlowSideEffects/eval_order.yul create mode 100644 test/libyul/controlFlowSideEffects/for_loop.yul create mode 100644 test/libyul/controlFlowSideEffects/leave.yul create mode 100644 test/libyul/controlFlowSideEffects/recursion.yul create mode 100644 test/libyul/controlFlowSideEffects/switch.yul diff --git a/test/libyul/controlFlowSideEffects/eval_order.yul b/test/libyul/controlFlowSideEffects/eval_order.yul new file mode 100644 index 000000000..a207d7a19 --- /dev/null +++ b/test/libyul/controlFlowSideEffects/eval_order.yul @@ -0,0 +1,19 @@ +{ + function a() -> x { + revert(0, 0) + } + function b() -> x { + return(0, 0) + } + function c() { + sstore(a(), b()) + } + function d() { + sstore(b(), a()) + } +} +// ---- +// a: can revert +// b: can terminate +// c: can terminate +// d: can revert diff --git a/test/libyul/controlFlowSideEffects/for_loop.yul b/test/libyul/controlFlowSideEffects/for_loop.yul new file mode 100644 index 000000000..1f3714a48 --- /dev/null +++ b/test/libyul/controlFlowSideEffects/for_loop.yul @@ -0,0 +1,55 @@ +{ + function a() { + for { leave } calldataload(0) { } { + break + revert(0, 0) + } + } + function b() { + for { } calldataload(0) { leave } { + break + revert(0, 0) + } + } + function b2() { + for { } calldataload(0) { leave } { + revert(0, 0) + } + } + function c() { + for { } calldataload(0) { revert(0, 0) } { + break + } + } + function c2() { + for { } calldataload(0) { revert(0, 0) } { + break + revert(0, 0) + } + } + function d() { + for { } calldataload(0) { revert(0, 0) } { + continue + } + } + function e() { + for { } calldataload(0) { revert(0, 0) } { + if calldataload(1) { break } + } + } + function f() { + for { } calldataload(0) { } { + if calldataload(1) { continue } + revert(0, 0) + } + } +} +// ---- +// a: can continue +// b: can continue +// b2: can revert, can continue +// c: can continue +// c2: can continue +// d: can revert, can continue +// e: can revert, can continue +// f: can revert, can continue diff --git a/test/libyul/controlFlowSideEffects/leave.yul b/test/libyul/controlFlowSideEffects/leave.yul new file mode 100644 index 000000000..bbc977820 --- /dev/null +++ b/test/libyul/controlFlowSideEffects/leave.yul @@ -0,0 +1,13 @@ +{ + function a() { + revert(0, 0) + leave + } + function b() { + leave + revert(0, 0) + } +} +// ---- +// a: can revert +// b: can continue diff --git a/test/libyul/controlFlowSideEffects/recursion.yul b/test/libyul/controlFlowSideEffects/recursion.yul new file mode 100644 index 000000000..c4176d502 --- /dev/null +++ b/test/libyul/controlFlowSideEffects/recursion.yul @@ -0,0 +1,37 @@ +{ + function a() { + if calldataload(0) { + revert(0, 0) + } + reg() + b() + } + function b() { + a() + return(0, 0) + } + function c() { + c() + revert(0, 0) + } + function d() { + switch calldataload(0) + case 0 { x() } + case 1 { y() reg() revert(0, 0) } + default { z() } + } + function x() { d() revert(0, 0) } + function y() { reg() x() } + function z() { y() } + + function reg() {} +} +// ---- +// a: can revert +// b: can revert +// c: +// d: +// reg: can continue +// x: +// y: +// z: diff --git a/test/libyul/controlFlowSideEffects/switch.yul b/test/libyul/controlFlowSideEffects/switch.yul new file mode 100644 index 000000000..63b45ce30 --- /dev/null +++ b/test/libyul/controlFlowSideEffects/switch.yul @@ -0,0 +1,41 @@ +{ + function a() { + switch calldataload(0) + case 0 { revert(0, 0) } + } + function b() { + switch calldataload(0) + case 0 { revert(0, 0) } + default { revert(0, 0) } + } + function c() { + return(0, 0) + switch calldataload(0) + case 0 { revert(0, 0) } + default { } + } + function d() { + switch calldataload(0) + case 0 { return(0, 0) } + default { return(0, 0) } + revert(0, 0) + } + function e() { + switch calldataload(0) + case 0 { return(0, 0) } + revert(0, 0) + } + function f() { + switch calldataload(0) + case 0 { leave } + default { leave } + revert(0, 0) + } +} +// ---- +// a: can revert, can continue +// b: can revert +// c: can terminate +// d: can terminate +// e: can terminate, can revert +// f: can continue From d6844943892e83a84816bd814573d1c614cbb1b1 Mon Sep 17 00:00:00 2001 From: Mariela Mantle Date: Fri, 8 Oct 2021 13:51:23 -0400 Subject: [PATCH 54/62] feat(docs): get mismatched Yul optimizer step lists back in sync --- docs/internals/optimizer.rst | 17 +++++++++-------- docs/yul.rst | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index e5de8a197..93179c041 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -275,7 +275,7 @@ The following transformation steps are the main components: - Common Subexpression Eliminator - Expression Simplifier - Redundant Assign Eliminator -- Full Function Inliner +- Full Inliner Optimizer Steps --------------- @@ -297,7 +297,8 @@ on the individual steps and their sequence below. - :ref:`for-loop-condition-into-body`. - :ref:`for-loop-condition-out-of-body`. - :ref:`for-loop-init-rewriter`. -- :ref:`functional-inliner`. +- :ref:`expression-inliner`. +- :ref:`full-inliner`. - :ref:`function-grouper`. - :ref:`function-hoister`. - :ref:`function-specializer`. @@ -1082,9 +1083,9 @@ The actual removal of the function is performed by the Unused Pruner. Function Inlining ----------------- -.. _functional-inliner: +.. _expression-inliner: -FunctionalInliner +ExpressionInliner ^^^^^^^^^^^^^^^^^ This component of the optimizer performs restricted function inlining by inlining functions that can be @@ -1107,12 +1108,12 @@ The result of this inlining is always a single expression. This component can only be used on sources with unique names. -.. _full-function-inliner: +.. _full-inliner: -FullFunctionInliner -^^^^^^^^^^^^^^^^^^^ +FullInliner +^^^^^^^^^^^ -The Full Function Inliner replaces certain calls of certain functions +The Full Inliner replaces certain calls of certain functions by the function's body. This is not very helpful in most cases, because it just increases the code size but does not have a benefit. Furthermore, code is usually very expensive and we would often rather have shorter diff --git a/docs/yul.rst b/docs/yul.rst index 0a90a2825..433f175f0 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -1265,6 +1265,7 @@ Abbreviation Full name ``a`` ``SSATransform`` ``t`` ``StructuralSimplifier`` ``u`` ``UnusedPruner`` +``p`` ``UnusedFunctionParameterPruner`` ``d`` ``VarDeclInitializer`` ============ =============================== From 025bbbad8225d8bb3aa6b2741e4be0dd66146289 Mon Sep 17 00:00:00 2001 From: Mikko Ohtamaa Date: Thu, 9 Sep 2021 20:00:26 +0200 Subject: [PATCH 55/62] Clarify block.* and tx.* values in off-chain calls Looks like this may vary between different EVM implementations and confuses users. --- docs/cheatsheet.rst | 6 ++++++ docs/units-and-global-variables.rst | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 4ff9118bc..d36a96360 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -130,6 +130,12 @@ Global Variables - ``type(T).min`` (``T``): the minimum value representable by the integer type ``T``, see :ref:`Type Information`. - ``type(T).max`` (``T``): the maximum value representable by the integer type ``T``, see :ref:`Type Information`. +.. note:: + When contracts are evaluated off-chain rather than in context of a transaction included in a + block, you should not assume that ``block.*`` and ``tx.*`` refer to values from any specific + block or transaction. These values are provided by the EVM implementation that executes the + contract and can be arbitrary. + .. note:: Do not rely on ``block.timestamp`` or ``blockhash`` as a source of randomness, unless you know what you are doing. diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 95438b85a..8a6173280 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -92,6 +92,12 @@ Block and Transaction Properties ``msg.value`` can change for every **external** function call. This includes calls to library functions. +.. note:: + When contracts are evaluated off-chain rather than in context of a transaction included in a + block, you should not assume that ``block.*`` and ``tx.*`` refer to values from any specific + block or transaction. These values are provided by the EVM implementation that executes the + contract and can be arbitrary. + .. note:: Do not rely on ``block.timestamp`` or ``blockhash`` as a source of randomness, unless you know what you are doing. From a67b3bdd584f6f556d00264964d362d93491c108 Mon Sep 17 00:00:00 2001 From: Zachinquarantine Date: Mon, 16 Aug 2021 19:45:30 -0400 Subject: [PATCH 56/62] Removes support for Debian Wheezy (7) As per the schedule on https://wiki.debian.org/LTS. The only reason I haven't fully removed support for Jesse (8) is because it's still in https://wiki.debian.org/LTS/Extended --- scripts/install_deps.sh | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index ddea2e8b7..4c1c352fb 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -179,16 +179,6 @@ case $(uname -s) in . /etc/os-release install_z3="" case $VERSION_ID in - 7) - #wheezy - echo "Installing solidity dependencies on Debian Wheezy (7.x)." - echo "ERROR - 'install_deps.sh' doesn't have Debian Wheezy support yet." - echo "See https://docs.soliditylang.org/en/latest/installing-solidity.html for manual instructions." - echo "If you would like to get 'install_deps.sh' working for Debian Wheezy, that would be fantastic." - echo "Drop us a message at https://gitter.im/ethereum/solidity-dev." - echo "See also https://github.com/ethereum/webthree-umbrella/issues/495 where we are working through Alpine support." - exit 1 - ;; 8) #jessie echo "Installing solidity dependencies on Debian Jesse (8.x)." From 07c98227aae25e2c1da8ec24627d86f76e0134d0 Mon Sep 17 00:00:00 2001 From: Zachinquarantine Date: Mon, 16 Aug 2021 19:56:45 -0400 Subject: [PATCH 57/62] Remove old, unsupported Ubuntu versions and adds new ones. https://releases.ubuntu.com/ --- scripts/install_deps.sh | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 4c1c352fb..6a9c12f3f 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -267,32 +267,11 @@ case $(uname -s) in echo "Installing solidity dependencies on Ubuntu Trusty Tahr (14.04)." echo "Or, you may also be running Linux Mint Qiana / Rebecca / Rafaela / Rosa (base: Ubuntu Trusty Tahr (14.04).)" ;; - utopic) - echo "Installing solidity dependencies on Ubuntu Utopic Unicorn (14.10)." - ;; - vivid) - echo "Installing solidity dependencies on Ubuntu Vivid Vervet (15.04)." - ;; - wily) - echo "Installing solidity dependencies on Ubuntu Wily Werewolf (15.10)." - ;; xenial|sarah|serena|sonya|sylvia) echo "Installing solidity dependencies on Ubuntu Xenial Xerus (16.04)." echo "Or, you may also be running Linux Mint Sarah / Serena / Sonya / Sylvia (base: Ubuntu Xenial Xerus (16.04).)" install_z3="libz3-dev" ;; - yakkety) - echo "Installing solidity dependencies on Ubuntu Yakkety Yak (16.10)." - install_z3="libz3-dev" - ;; - zesty) - echo "Installing solidity dependencies on Ubuntu Zesty (17.04)." - install_z3="libz3-dev" - ;; - artful) - echo "Installing solidity dependencies on Ubuntu Artful (17.10)." - install_z3="libz3-dev" - ;; bionic) echo "Installing solidity dependencies." install_z3="libz3-dev" @@ -301,6 +280,10 @@ case $(uname -s) in echo "Installing solidity dependencies." install_z3="libz3-dev" ;; + hirsute) + echo "Installing solidity dependencies." + install_z3="libz3-dev" + ;; betsy) #do not try anything for betsy. echo "Linux Mint Betsy is not supported at the moment as it runs off of Debian." @@ -315,7 +298,7 @@ case $(uname -s) in echo "ERROR - Unknown or unsupported Ubuntu version ($(lsb_release -cs))" echo "ERROR - This might not work, but we are trying anyway." echo "Please drop us a message at https://gitter.im/ethereum/solidity-dev." - echo "We only support Trusty, Utopic, Vivid, Wily, Xenial, Yakkety, Zesty, Artful and Bionic." + echo "We only support Trusty, Xenial, Bionic, Focal, and Hirsute." install_z3="libz3-dev" ;; esac From ba0c09e08269ffb3924cadf95a1d937f65821ce4 Mon Sep 17 00:00:00 2001 From: tcoyvwac <53616399+tcoyvwac@users.noreply.github.com> Date: Thu, 14 Oct 2021 01:16:10 +0200 Subject: [PATCH 58/62] Prefer make_unique over new --- libsolidity/formal/CHC.cpp | 2 +- tools/solidityUpgrade/SourceUpgrade.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index fc97ab0ca..f0072313b 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -991,7 +991,7 @@ void CHC::resetSourceAnalysis() if (usesZ3) { /// z3::fixedpoint does not have a reset mechanism, so we need to create another. - m_interface.reset(new Z3CHCInterface(m_settings.timeout)); + m_interface = std::make_unique(m_settings.timeout); auto z3Interface = dynamic_cast(m_interface.get()); solAssert(z3Interface, ""); m_context.setSolver(z3Interface->z3Interface()); diff --git a/tools/solidityUpgrade/SourceUpgrade.cpp b/tools/solidityUpgrade/SourceUpgrade.cpp index c102be387..7c70b1d16 100644 --- a/tools/solidityUpgrade/SourceUpgrade.cpp +++ b/tools/solidityUpgrade/SourceUpgrade.cpp @@ -533,7 +533,7 @@ void SourceUpgrade::resetCompiler() void SourceUpgrade::resetCompiler(ReadCallback::Callback const& _callback) { - m_compiler.reset(new CompilerStack(_callback)); + m_compiler = std::make_unique(_callback); m_compiler->setSources(m_sourceCodes); m_compiler->setParserErrorRecovery(true); } From 5d985a24ac073330e04f495fdc69a733d40ed678 Mon Sep 17 00:00:00 2001 From: vowchick <37148723+vowchick@users.noreply.github.com> Date: Sat, 16 Oct 2021 11:54:46 +0300 Subject: [PATCH 59/62] Use range-v3 loops: delete boost includes An addition to issue #10738, couldn't change boost::for_each to std::for_each, doesn't compile. Build successful ./scripts/test.sh successful --- libsolidity/analysis/PostTypeChecker.cpp | 1 - libsolidity/ast/Types.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index cdc8c8b7e..d08ee78b7 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -25,7 +25,6 @@ #include #include -#include #include using namespace std; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 70e3ec298..fe0ac8ef8 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -41,7 +41,6 @@ #include #include #include -#include #include #include From 70d78a09a7b61aa9c1552bc59da4bd47a0375640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 15 Oct 2021 13:59:17 +0200 Subject: [PATCH 60/62] Remove `brew update` and the workarounds it requires --- .circleci/config.yml | 53 --------------------------- .circleci/osx_install_dependencies.sh | 3 -- 2 files changed, 56 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ea790cf02..a859b8464 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -160,35 +160,6 @@ defaults: - store_test_results: *store_test_results - store_artifacts: *artifacts_test_results - - steps_homebrew_workaround_before_restore_cache: &steps_homebrew_workaround_before_restore_cache - steps: - - run: - # Homebrew has recently replaced one of its dirs with a symlink to another. - # This makes tar used by restore_cache fail - the image contains an older version of - # Homebrew installed where it's a directory and tar refuses to overwrite a dir with a link. - # Removing the directory manually is a workaround that works only in case we do have - # cached files to restore. If we don't, we still need this dir because it contains - # a git wrapper that Homebrew uses to update itself. The solution is to just rename the - # dir before restore_cache and renamed it back afterwards. - # See https://github.com/ethereum/solidity/pull/12106 for more details. - name: Workaround for restore_cache + /usr/local/Homebrew/Library/Homebrew/shims/scm/ - command: | - cd /usr/local/Homebrew/Library/Homebrew/shims/ - mv scm/ scm-backup/ - - - steps_homebrew_workaround_after_restore_cache: &steps_homebrew_workaround_after_restore_cache - steps: - - run: - name: Workaround for restore_cache + /usr/local/Homebrew/Library/Homebrew/shims/scm/ - command: | - cd /usr/local/Homebrew/Library/Homebrew/shims/ - if ! [[ -e scm/ ]] - then - mv scm-backup/ scm/ - else - rm -r scm-backup/ - fi - - test_ubuntu1604_clang: &test_ubuntu1604_clang docker: - image: << pipeline.parameters.ubuntu-1604-clang-ossfuzz-docker-image >> @@ -654,19 +625,11 @@ jobs: MAKEFLAGS: -j 5 steps: - checkout - - when: - condition: true - # FIXME: Remove this workaround when CircleCI fixes restore_cache. - <<: *steps_homebrew_workaround_before_restore_cache - restore_cache: keys: - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} # DO NOT EDIT between here and save_cache, but rather edit ./circleci/osx_install_dependencies.sh # WARNING! If you do edit anything here instead, remember to invalidate the cache manually. - - when: - condition: true - # FIXME: Remove this workaround when CircleCI fixes restore_cache. - <<: *steps_homebrew_workaround_after_restore_cache - run: name: Install build dependencies command: ./.circleci/osx_install_dependencies.sh @@ -698,17 +661,9 @@ jobs: TERM: xterm steps: - checkout - - when: - condition: true - # FIXME: Remove this workaround when CircleCI fixes restore_cache. - <<: *steps_homebrew_workaround_before_restore_cache - restore_cache: keys: - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} - - when: - condition: true - # FIXME: Remove this workaround when CircleCI fixes restore_cache. - <<: *steps_homebrew_workaround_after_restore_cache - attach_workspace: at: . - run: *run_soltest @@ -722,17 +677,9 @@ jobs: TERM: xterm steps: - checkout - - when: - condition: true - # FIXME: Remove this workaround when CircleCI fixes restore_cache. - <<: *steps_homebrew_workaround_before_restore_cache - restore_cache: keys: - dependencies-osx-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} - - when: - condition: true - # FIXME: Remove this workaround when CircleCI fixes restore_cache. - <<: *steps_homebrew_workaround_after_restore_cache - attach_workspace: at: . - run: *run_cmdline_tests diff --git a/.circleci/osx_install_dependencies.sh b/.circleci/osx_install_dependencies.sh index b2f4b4e10..ed11f2491 100755 --- a/.circleci/osx_install_dependencies.sh +++ b/.circleci/osx_install_dependencies.sh @@ -52,9 +52,6 @@ function validate_checksum { if [ ! -f /usr/local/lib/libz3.a ] # if this file does not exists (cache was not restored), rebuild dependencies then - git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow - git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow - brew update brew unlink python brew install boost brew install cmake From 8dfb390c7ee778b0f32fc68d216bf886d8f6a526 Mon Sep 17 00:00:00 2001 From: Marenz Date: Wed, 13 Oct 2021 13:19:47 +0200 Subject: [PATCH 61/62] Enhance documentation in regards to modifiers and return --- docs/ir/ir-breaking-changes.rst | 44 +++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/docs/ir/ir-breaking-changes.rst b/docs/ir/ir-breaking-changes.rst index 9223b3763..8afbc58c3 100644 --- a/docs/ir/ir-breaking-changes.rst +++ b/docs/ir/ir-breaking-changes.rst @@ -1,3 +1,6 @@ + +.. index: ir breaking changes + ********************************* Solidity IR-based Codegen Changes ********************************* @@ -35,13 +38,15 @@ hiding new and different behavior in existing code. We have the same behavior for implicit delete, for example when array of structs is shortened. -- Function modifiers are implemented in a slightly different way regarding function parameters. +- Function modifiers are implemented in a slightly different way regarding function parameters and return variables. This especially has an effect if the placeholder ``_;`` is evaluated multiple times in a modifier. - In the old code generator, each function parameter has a fixed slot on the stack. If the function - is run multiple times because ``_;`` is used multiple times or used in a loop, then a change to the - function parameter's value is visible in the next execution of the function. + In the old code generator, each function parameter and return variable has a fixed slot on the stack. + If the function is run multiple times because ``_;`` is used multiple times or used in a loop, then a + change to the function parameter's or return variable's value is visible in the next execution of the function. The new code generator implements modifiers using actual functions and passes function parameters on. - This means that multiple executions of a function will get the same values for the parameters. + This means that multiple evaluations of a function's body will get the same values for the parameters, + and the effect on return variables is that they are reset to their default (zero) value for each + execution. .. code-block:: solidity @@ -57,6 +62,35 @@ hiding new and different behavior in existing code. If you execute ``f(0)`` in the old code generator, it will return ``2``, while it will return ``1`` when using the new code generator. + .. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.7.1 <0.9.0; + + contract C { + bool active = true; + modifier mod() + { + _; + active = false; + _; + } + function foo() external mod() returns (uint ret) + { + if (active) + ret = 1; // Same as ``return 1`` + } + } + + The function ``C.foo()`` returns the following values: + + - Old code generator: ``1`` as the return variable is initialized to ``0`` only once before the first ``_;`` + evaluation and then overwritten by the ``return 1;``. It is not initialized again for the second ``_;`` + evaluation and ``foo()`` does not explicitly assign it either (due to ``active == false``), thus it keeps + its first value. + - New code generator: ``0`` as all parameters, including return parameters, will be re-initialized before + each ``_;`` evaluation. + - The order of contract initialization has changed in case of inheritance. The order used to be: From 121f9c3b7483f9bfab87d5eb02a36ef457e08365 Mon Sep 17 00:00:00 2001 From: William Entriken Date: Tue, 5 Oct 2021 20:51:59 -0400 Subject: [PATCH 62/62] More strongly recommend to use the latest version --- docs/index.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index d702a28c9..fadc252fc 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,8 +17,10 @@ With Solidity you can create contracts for uses such as voting, crowdfunding, bl and multi-signature wallets. When deploying contracts, you should use the latest released -version of Solidity. This is because breaking changes as well as -new features and bug fixes are introduced regularly. We currently use +version of Solidity. Apart from exceptional cases, only the latest version receives +`security fixes`. +Furthermore, breaking changes as well as +new features are introduced regularly. We currently use a 0.x version number `to indicate this fast pace of change `_. .. warning::