From 9024b7c30e624e75ea265bb6c743a67dae25dbee Mon Sep 17 00:00:00 2001 From: IgorKoval Date: Tue, 2 May 2023 23:13:23 +0300 Subject: [PATCH] 0.69.0 --- API.md | 12 +- Cargo.lock | 208 +++++------------- Changelog_TON.md | 39 +++- compiler/CMakeLists.txt | 2 +- compiler/liblangutil/CMakeLists.txt | 2 + compiler/liblangutil/TVMVersion.h | 77 +++++++ compiler/libsolidity/CMakeLists.txt | 2 +- .../libsolidity/analysis/SyntaxChecker.cpp | 17 +- compiler/libsolidity/ast/Types.cpp | 2 + .../libsolidity/codegen/PeepholeOptimizer.cpp | 11 +- compiler/libsolidity/codegen/TVM.cpp | 7 +- .../libsolidity/codegen/{TVM.h => TVM.hpp} | 9 +- compiler/libsolidity/codegen/TVMABI.cpp | 15 +- compiler/libsolidity/codegen/TVMCommons.cpp | 40 ++-- compiler/libsolidity/codegen/TVMCommons.hpp | 14 +- .../codegen/TVMContractCompiler.hpp | 2 +- .../codegen/TVMExpressionCompiler.cpp | 4 +- .../libsolidity/codegen/TVMFunctionCall.cpp | 4 +- .../codegen/TVMFunctionCompiler.cpp | 71 +++--- compiler/libsolidity/codegen/TVMPusher.cpp | 21 +- .../libsolidity/codegen/TVMTypeChecker.cpp | 76 +++++++ .../libsolidity/codegen/TVMTypeChecker.hpp | 3 + compiler/libsolidity/codegen/TvmAst.cpp | 20 +- compiler/libsolidity/codegen/TvmAst.hpp | 3 +- .../libsolidity/interface/CompilerStack.cpp | 13 +- .../libsolidity/interface/CompilerStack.h | 6 +- .../interface/StandardCompiler.cpp | 13 +- .../libsolidity/interface/StandardCompiler.h | 1 + compiler/solc/CommandLineInterface.cpp | 2 +- compiler/solc/CommandLineParser.cpp | 16 ++ compiler/solc/CommandLineParser.h | 2 + sold/Cargo.toml | 2 +- sold/src/lib.rs | 34 ++- 33 files changed, 459 insertions(+), 291 deletions(-) create mode 100644 compiler/liblangutil/TVMVersion.h rename compiler/libsolidity/codegen/{TVM.h => TVM.hpp} (79%) diff --git a/API.md b/API.md index b77ef9f8..b8170bc7 100644 --- a/API.md +++ b/API.md @@ -2261,7 +2261,6 @@ Example: ```TVMSolidity pragma ton-solidity >= 0.35.0; pragma AbiHeader expire; -pragma AbiHeader time; pragma AbiHeader pubkey; import "https://github.com/tonlabs/debots/raw/9c6ca72b648fa51962224ec0d7ce91df2a0068c1/Debot.sol"; @@ -2323,24 +2322,19 @@ Turns off binary operation result overflow check. #### pragma AbiHeader ```TVMSolidity -pragma AbiHeader time; +pragma AbiHeader notime; pragma AbiHeader pubkey; pragma AbiHeader expire; ``` Defines headers that are used in external messages: +* `notime` - disables `time` abi header, which is enabled by default. Abi header `time` – `uint64` local time when message was created, used for replay protection * `pubkey` (`uint256`) - optional public key that the message can be signed with. -* `time` (`uint64`) - local time when message was created. Used for replay protection. -* `expire` (`uint32`) - time when the message should be meant as expired. +* `expire` (`uint32`) - time when the message should be meant as expired. **Note:** -- `time` presents in external messages if `pragma AbiHeader time` is used OR there is no -`afterSignatureCheck` function defined in the contract. -- `time` doesn't present in external messages if `pragma AbiHeader time` isn't used AND there -is `afterSignatureCheck` function defined in the contract. - Defined headers are listed in `*.abi.json` file in `header` section. See also: [Contract execution](#contract-execution), [afterSignatureCheck](#aftersignaturecheck), diff --git a/Cargo.lock b/Cargo.lock index 608064d4..4b13f6fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,9 +51,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" dependencies = [ "memchr", ] @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" dependencies = [ "anstyle", "anstyle-parse", @@ -117,9 +117,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" dependencies = [ "anstyle", "windows-sys", @@ -257,9 +257,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" [[package]] name = "byteorder" @@ -323,9 +323,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.2.3" +version = "4.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f9152d70e42172fdb87de2efd7327160beee37886027cf86f30a233d5b30b4" +checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" dependencies = [ "clap_builder", "clap_derive", @@ -334,9 +334,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.2.3" +version = "4.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e067b220911598876eb55d52725ddcc201ffe3f0904018195973bc5b012ea2ca" +checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" dependencies = [ "anstream", "anstyle", @@ -354,7 +354,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -372,16 +372,6 @@ dependencies = [ "cc", ] -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "colorchoice" version = "1.0.0" @@ -402,9 +392,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" dependencies = [ "libc", ] @@ -465,50 +455,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "cxx" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.15", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - [[package]] name = "difflib" version = "0.4.0" @@ -562,9 +508,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dunce" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "ed25519" @@ -734,12 +680,11 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] @@ -791,9 +736,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "68c16e1bfd491478ab155fd8b4896b86f9ede344949b641e61501e07c2b8b4d5" dependencies = [ "wasm-bindgen", ] @@ -806,24 +751,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.141" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" - -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "linux-raw-sys" -version = "0.3.2" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f508063cc7bb32987c71511216bd5a32be15bccb6a80b52df8b9d7f01fc3aa2" +checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" [[package]] name = "lockfree" @@ -979,9 +915,9 @@ checksum = "30fceb411f9a12ff9222c5f824026be368ff15dc2f13468d850c7d3f502205d6" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "ppv-lite86" @@ -1022,18 +958,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" dependencies = [ "proc-macro2", ] @@ -1128,9 +1064,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.3" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" dependencies = [ "aho-corasick", "memchr", @@ -1145,9 +1081,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] name = "rust-argon2" @@ -1169,9 +1105,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.37.12" +version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "722529a737f5a942fdbac3a46cee213053196737c5eaa3386d52e85b786f2659" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ "bitflags", "errno", @@ -1187,30 +1123,24 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" - [[package]] name = "serde" -version = "1.0.160" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -1282,11 +1212,11 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "sold" -version = "0.68.0" +version = "0.69.0" dependencies = [ "assert_cmd", "atty", - "clap 4.2.3", + "clap 4.2.7", "cmake", "dunce", "failure", @@ -1341,9 +1271,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" dependencies = [ "proc-macro2", "quote", @@ -1373,15 +1303,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - [[package]] name = "termtree" version = "0.4.1" @@ -1633,9 +1554,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1643,24 +1564,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.16", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1668,22 +1589,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.16", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb" [[package]] name = "winapi" @@ -1701,15 +1622,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1819,7 +1731,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] diff --git a/Changelog_TON.md b/Changelog_TON.md index 98293490..169de9f4 100644 --- a/Changelog_TON.md +++ b/Changelog_TON.md @@ -1,6 +1,21 @@ +### 0.69.0 (2023-05-15) + +Breaking changes: +* `pragma AbiHeader time` is no longer allowed for use. Timestamp in header of external message is enabled by default and can be disabled with `pragma AbiHeader notime`. + +Compiler features: + * Supported generating code for The Open Network. Use command line option `--tvm-version ton`. We don't use `ZERO(SWAP|ROTR)IF[NOT][2]`, `COPYLEFT`, `INITCODEHASH`, `MYCODE`, `STORAGEFEE`, `LDCONT`, `STCONT` and another opcodes for ton. + +Optimizations: + * Improved constant analyzer that compile more optimal code for `require`/`revert` functions and another cases. + +Bugfixes: + * Fixed segmentation fault that could occur in some cases of using `var[U]Int` types. + * Fixed segmentation fault that occurred in constructions `optional(T1, T2) x = null;` and some another cases. + ### 0.68.0 (2023-04-19) -Breaking change: +Breaking changes: * `require()` and `revert()` take `uint16` exception code instead of `uint256`. * `tvm.rawConfigParam(...)` returns `optional(TvmCell)` instead of `(TvmCell, bool)`. * Exit status of `solc`/`sold` is equal to `0` and it prints `Compiler run successful, no output requested.` if the source contain no deployable contracts. @@ -38,7 +53,7 @@ Bugfixes: * Fixed problem with getting inherited function `afterSignatureCheck`. * Support overloading for function `onCodeUpgrade`. -Breaking change: +Breaking changes: * Function `onCodeUpgrade` had function id = 2. Now, it has another id, but you can set `functionID(2)` in new contracts to upgrade old ones. @@ -129,7 +144,7 @@ Bugfixes: * Fixed problem with fetching `varInt` from mappings that use `varInt` as value. * Fixed problem with control flow in `do{ ...} while(...)` construction. -Breaking change: +Breaking changes: * `value`, `bounce` and `flag` options in return statement of `responsible` function must be explicitly defined. @@ -207,7 +222,7 @@ Compiler features: * Supported `abi.encode()`/`abi.decode()`. * Supported keyword `emptyMap`. -Breaking change: +Breaking changes: * Supported `mapping`'s in constructor of structures. Bugfix: @@ -220,7 +235,7 @@ Bugfix: Bugfixes: * Fix issue when it was impossible to import 2 files from each other. -Breaking change: +Breaking changes: * Output AST JSON as pure json without `====` separators or something else. * Deleted option "abiVer" from `tvm.buildExtMsg()` and sending external inbound message for debots. @@ -242,7 +257,7 @@ Compiler features: * Supported `tvm.setGasLimit(uint)`. * Supported constant arrays, e.g. `uint[] public constant fib = [uint(2), 3, 5, 8, 12, 20, 32];`. -Breaking change: +Breaking changes: * Changed `stoi()` return type to `optional(int)`. * Output AST JSON to the file instead of standard output. @@ -259,7 +274,7 @@ Compiler features: * Checked if `stateInit` is valid before deploying. * Supported tvm.buildDataInit(). -Breaking change: +Breaking changes: * Deleted `tvm.buildEmptyData()`. Use `tvm.buildDataInit()`. Gas optimizations: @@ -273,7 +288,7 @@ Compiler features: * Added keyword `null`. * Supported concatenation `string` and `bytesN` types. -Breaking change: +Breaking changes: * Deleted `\.bitsAndRefs()`. Please, use `\.size()`. * Renamed `\.bitsAndRefs()` -> `\.size()`. * Deleted `tvm.deploy()`. Please, use `\.transfer({stateInit: ..., ...})`. @@ -305,7 +320,7 @@ Support ABI 2.1: Bugfixes: * Fixed an issue when a function can be called but constructor hasn't been called yet. -Breaking change: +Breaking changes: * Syntax of creating and sending of an external inbound message changed from option `{extMsg: true}` to suffix `.extMsg`. * Rename `_answer_id` to `answerId` for responsible functions. @@ -318,7 +333,7 @@ Compiler features: * Added serialization to builder and deserialization from slice for "enum" type values. * Support synchronous calls with `.await` suffix. -Breaking change: +Breaking changes: * Throw exception with code 72 on external message invocations for the functions with modifier `internalMsg`. Bugfixes: @@ -336,7 +351,7 @@ Compiler features: * Support `msg.isInternal`, `msg.isExternal` and `msg.isTickTock`. * Support `storeOnes` and `storeZeroes` for `TvmBuilder`. -Breaking change: +Breaking changes: * Change behavior of function `.substr()`. * Use `{dest: ...}` instead of `.extAddr(...)` in emit statement to set destination address. @@ -387,7 +402,7 @@ Changes: ### 0.42.0 (2021-04-19) -Breaking change: +Breaking changes: * Calling a fallback function (instead of throwing error) in cases: 1. Bit length of the internal input message is between 1 and 31. 2. The message has zero bit size and not zero count of references. diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt index b7d45346..0b17854a 100644 --- a/compiler/CMakeLists.txt +++ b/compiler/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.68.0") +set(PROJECT_VERSION "0.69.0") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/compiler/liblangutil/CMakeLists.txt b/compiler/liblangutil/CMakeLists.txt index 2c187f6d..31210220 100644 --- a/compiler/liblangutil/CMakeLists.txt +++ b/compiler/liblangutil/CMakeLists.txt @@ -27,6 +27,8 @@ set(sources Token.h UndefMacros.h UniqueErrorReporter.h + + TVMVersion.h ) add_library(langutil ${sources}) diff --git a/compiler/liblangutil/TVMVersion.h b/compiler/liblangutil/TVMVersion.h new file mode 100644 index 00000000..f0448c01 --- /dev/null +++ b/compiler/liblangutil/TVMVersion.h @@ -0,0 +1,77 @@ +/* + 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 +/** + * TVM versioning. + */ + +#pragma once + +#include +#include + +#include + + +namespace solidity::langutil +{ + +/** + * A version specifier of the TVM we want to compile to. + */ +class TVMVersion: + boost::less_than_comparable, + boost::equality_comparable +{ +public: + TVMVersion() = default; + + static TVMVersion ever() { return TVMVersion{Version::Ever}; } + static TVMVersion ton() { return TVMVersion{Version::Ton}; } + static TVMVersion gosh() { return TVMVersion{Version::Gosh}; } + + static std::optional fromString(std::string const& _version) + { + for (auto const& v: {ever(), ton(), gosh()}) + if (_version == v.name()) + return v; + return std::nullopt; + } + + bool operator==(TVMVersion const& _other) const { return m_version == _other.m_version; } + bool operator<(TVMVersion const& _other) const { return m_version < _other.m_version; } + + std::string name() const + { + switch (m_version) + { + case Version::Ever: return "ever"; + case Version::Ton: return "ton"; + case Version::Gosh: return "gosh"; + } + return "INVALID"; + } + +private: + enum class Version { Ever, Ton, Gosh }; + + explicit TVMVersion(Version _version): m_version(_version) {} + + Version m_version = Version::Ever; +}; + +} diff --git a/compiler/libsolidity/CMakeLists.txt b/compiler/libsolidity/CMakeLists.txt index 4fbc8404..3f433b62 100644 --- a/compiler/libsolidity/CMakeLists.txt +++ b/compiler/libsolidity/CMakeLists.txt @@ -116,7 +116,7 @@ set(sources codegen/StackOptimizer.cpp codegen/StackOptimizer.hpp codegen/TVM.cpp - codegen/TVM.h + codegen/TVM.hpp codegen/TVMABI.cpp codegen/TVMABI.hpp codegen/TVMAnalyzer.cpp diff --git a/compiler/libsolidity/analysis/SyntaxChecker.cpp b/compiler/libsolidity/analysis/SyntaxChecker.cpp index 459cf4e3..42a776d2 100644 --- a/compiler/libsolidity/analysis/SyntaxChecker.cpp +++ b/compiler/libsolidity/analysis/SyntaxChecker.cpp @@ -183,9 +183,20 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma) } else if (_pragma.literals()[0] == "AbiHeader") { - if (_pragma.literals().size() != 2 || - (_pragma.literals()[1] != "time" && _pragma.literals()[1] != "pubkey" && _pragma.literals()[1] != "expire")) { - m_errorReporter.syntaxError(228_error, _pragma.location(), "Correct format: pragma AbiHeader [time|pubkey|expire]"); + const std::string base = "Correct format: pragma AbiHeader [pubkey|expire|notime]"; + if (_pragma.literals().size() != 2) { + auto err = "Empty pragma. " + base; + m_errorReporter.syntaxError(228_error, _pragma.location(), err); + } else { + auto literal = _pragma.literals()[1]; + if (literal != "pubkey" && literal != "expire" && literal != "notime") { + auto err = "Unknown pragma \""+ literal + "\". " + base; + if (literal == "time") { + err += "\nNote: timestamp in header of external message " + "is on by default, so delete this pragma."; + } + m_errorReporter.syntaxError(228_error, _pragma.location(), err); + } } } else if (_pragma.literals()[0] == "upgrade") diff --git a/compiler/libsolidity/ast/Types.cpp b/compiler/libsolidity/ast/Types.cpp index 3a6f54de..26f8cc6c 100644 --- a/compiler/libsolidity/ast/Types.cpp +++ b/compiler/libsolidity/ast/Types.cpp @@ -5704,6 +5704,8 @@ TypeResult VarInteger::unaryOperatorResult(Token _operator) const { TypeResult VarInteger::binaryOperatorResult(Token _operator, Type const* _other) const { Type const* resultType = m_int.binaryOperatorResult(_operator, _other); + if (resultType == nullptr) + return nullptr; if (resultType->isImplicitlyConvertibleTo(*this)) { resultType = this; } diff --git a/compiler/libsolidity/codegen/PeepholeOptimizer.cpp b/compiler/libsolidity/codegen/PeepholeOptimizer.cpp index f433e575..68a82843 100644 --- a/compiler/libsolidity/codegen/PeepholeOptimizer.cpp +++ b/compiler/libsolidity/codegen/PeepholeOptimizer.cpp @@ -18,11 +18,12 @@ #include -#include "TvmAst.hpp" -#include "TVMConstants.hpp" #include "PeepholeOptimizer.hpp" -#include "TVMPusher.hpp" #include "StackOpcodeSquasher.hpp" +#include "TVM.hpp" +#include "TVMConstants.hpp" +#include "TVMPusher.hpp" +#include "TvmAst.hpp" using namespace std; using namespace solidity::util; @@ -497,6 +498,10 @@ std::optional PrivatePeepholeOptimizer::optimizeAt1(Pointer // IF[ELSE][NOT][JMP] if (m_withUnpackOpaque && cmd1IfElse) { for (bool isZero : {true, false}) { + if (isZero && *GlobalParams::g_tvmVersion == langutil::TVMVersion::ton()){ + // ignore ZERO SWAP/ROTR IF [NOT] + continue; + } for (bool isSwap : {true, false}) { for (bool trueBranch: {true, false}) { Pointer curBranch = trueBranch ? cmd1IfElse->trueBody() : cmd1IfElse->falseBody(); diff --git a/compiler/libsolidity/codegen/TVM.cpp b/compiler/libsolidity/codegen/TVM.cpp index f0f524a3..552444a0 100644 --- a/compiler/libsolidity/codegen/TVM.cpp +++ b/compiler/libsolidity/codegen/TVM.cpp @@ -17,14 +17,15 @@ */ -#include "TVM.h" +#include "TVM.hpp" #include "TVMContractCompiler.hpp" using namespace std; using namespace solidity::frontend; solidity::langutil::ErrorReporter* GlobalParams::g_errorReporter{}; -solidity::frontend::CompilerStack* GlobalParams::g_compilerStack{}; +solidity::langutil::CharStreamProvider* GlobalParams::g_charStreamProvider{}; +solidity::util::SetOnce GlobalParams::g_tvmVersion{}; std::string getPathToFiles( const std::string& solFileName, @@ -61,7 +62,7 @@ std::string getPathToFiles( void TVMCompilerProceedContract( ContractDefinition const& _contract, - std::vector> _sourceUnits, + std::vector> const& _sourceUnits, std::vector const* pragmaDirectives, bool generateAbi, bool generateCode, diff --git a/compiler/libsolidity/codegen/TVM.h b/compiler/libsolidity/codegen/TVM.hpp similarity index 79% rename from compiler/libsolidity/codegen/TVM.h rename to compiler/libsolidity/codegen/TVM.hpp index dc36f1a6..3f85c3c0 100644 --- a/compiler/libsolidity/codegen/TVM.h +++ b/compiler/libsolidity/codegen/TVM.hpp @@ -20,13 +20,16 @@ #include #include +#include #include -#include +#include +#include class GlobalParams { public: static solidity::langutil::ErrorReporter* g_errorReporter; - static solidity::frontend::CompilerStack* g_compilerStack; + static solidity::langutil::CharStreamProvider* g_charStreamProvider; + static solidity::util::SetOnce g_tvmVersion; }; std::string getPathToFiles( @@ -37,7 +40,7 @@ std::string getPathToFiles( void TVMCompilerProceedContract( solidity::frontend::ContractDefinition const& _contract, - std::vector> _sourceUnits, + std::vector> const& _sourceUnits, std::vector const* pragmaDirectives, bool generateAbi, bool generateCode, diff --git a/compiler/libsolidity/codegen/TVMABI.cpp b/compiler/libsolidity/codegen/TVMABI.cpp index 59951914..4e9ed405 100644 --- a/compiler/libsolidity/codegen/TVMABI.cpp +++ b/compiler/libsolidity/codegen/TVMABI.cpp @@ -23,7 +23,7 @@ #include "TVMABI.hpp" #include "TVMPusher.hpp" -#include "TVM.h" +#include "TVM.hpp" #include "TVMConstants.hpp" #include "TVMContractCompiler.hpp" @@ -119,11 +119,12 @@ Json::Value TVMABI::generateABIJson( // header { Json::Value header(Json::arrayValue); - for (const std::string h : {"pubkey", "time", "expire"}) { - if (std::get<0>(pdh.hasHeader(h)) || (h == "time" && ctx.hasTimeInAbiHeader())) { - header.append(h); - } - } + + // NOTE: order is important + if (pdh.hasPubkey()) header.append("pubkey"); + if (pdh.hasTime()) header.append("time"); + if (pdh.hasExpire()) header.append("expire"); + root["header"] = header; } @@ -605,7 +606,7 @@ int ChainDataDecoder::maxBits(bool isResponsible) { // external inbound message int maxUsed = TvmConst::Abi::MaxOptionalSignLength + (pusher->ctx().pragmaHelper().hasPubkey()? 1 + 256 : 0) + - (pusher->ctx().hasTimeInAbiHeader()? 64 : 0) + + (pusher->ctx().pragmaHelper().hasTime()? 64 : 0) + (pusher->ctx().pragmaHelper().hasExpire()? 32 : 0) + 32 + // functionID (isResponsible ? 32 : 0); // callback function diff --git a/compiler/libsolidity/codegen/TVMCommons.cpp b/compiler/libsolidity/codegen/TVMCommons.cpp index 27f70e02..6f3371d4 100644 --- a/compiler/libsolidity/codegen/TVMCommons.cpp +++ b/compiler/libsolidity/codegen/TVMCommons.cpp @@ -20,7 +20,7 @@ #include -#include "TVM.h" +#include "TVM.hpp" #include "TVMCommons.hpp" #include "TVMConstants.hpp" @@ -657,35 +657,27 @@ std::string StrUtils::toBinString(bigint num) { } std::optional ExprUtils::constValue(const Expression &_e) { - auto f = [](VariableDeclaration const* vd) -> std::optional { - if (vd != nullptr && vd->isConstant() && vd->value() != nullptr) { - return constValue(*vd->value()); + if (*_e.annotation().isPure) { + if (auto memberAccess = to(&_e)) { + if (auto variable = dynamic_cast(memberAccess->annotation().referencedDeclaration)) { + return constValue(*variable->value()); + } } - return {}; - }; - if (*_e.annotation().isPure) { if (auto ident = to(&_e)) { IdentifierAnnotation &identifierAnnotation = ident->annotation(); - const auto *vd = to(identifierAnnotation.referencedDeclaration); - return f(vd); - } else if (_e.annotation().type->category() == Type::Category::RationalNumber) { - auto number = dynamic_cast(_e.annotation().type); - solAssert(number, ""); - bigint val = number->value2(); - return val; - } - } else { - // MyLibName.const_variable - auto memberAccess = to(&_e); - if (memberAccess) { - auto identifier = to(&memberAccess->expression()); - if (identifier && identifier->annotation().type->category() == Type::Category::TypeType) { - auto vd = to(memberAccess->annotation().referencedDeclaration); - return f(vd); - } + const auto *variable = to(identifierAnnotation.referencedDeclaration); + return constValue(*variable->value()); } } + + if (_e.annotation().type->category() == Type::Category::RationalNumber) { + auto number = dynamic_cast(_e.annotation().type); + solAssert(number, ""); + bigint val = number->value2(); + return val; + } + return {}; } diff --git a/compiler/libsolidity/codegen/TVMCommons.hpp b/compiler/libsolidity/codegen/TVMCommons.hpp index 8a9d82b8..1e601836 100644 --- a/compiler/libsolidity/codegen/TVMCommons.hpp +++ b/compiler/libsolidity/codegen/TVMCommons.hpp @@ -183,17 +183,9 @@ class PragmaDirectiveHelper { pragmaDirectives{_pragmaDirectives} { } - bool hasPubkey() const { - return std::get<0>(hasHeader("pubkey")); - } - - bool hasTime() const { - return std::get<0>(hasHeader("time")); - } - - bool hasExpire() const { - return std::get<0>(hasHeader("expire")); - } + bool hasTime() const { return !std::get<0>(hasHeader("notime")); } + bool hasPubkey() const { return std::get<0>(hasHeader("pubkey")); } + bool hasExpire() const { return std::get<0>(hasHeader("expire")); } std::tuple hasHeader(const std::string& str) const { for (PragmaDirective const *pd : pragmaDirectives) { diff --git a/compiler/libsolidity/codegen/TVMContractCompiler.hpp b/compiler/libsolidity/codegen/TVMContractCompiler.hpp index 1bd96e04..e1565c13 100644 --- a/compiler/libsolidity/codegen/TVMContractCompiler.hpp +++ b/compiler/libsolidity/codegen/TVMContractCompiler.hpp @@ -18,7 +18,7 @@ #pragma once -#include "TVM.h" +#include "TVM.hpp" #include "TVMPusher.hpp" #include "TvmAst.hpp" diff --git a/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp b/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp index 596af530..55bd52c3 100644 --- a/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp +++ b/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp @@ -25,7 +25,7 @@ #include "TVMExpressionCompiler.hpp" #include "TVMFunctionCall.hpp" #include "TVMStructCompiler.hpp" -#include "TVM.h" +#include "TVM.hpp" using namespace solidity::frontend; using namespace solidity::langutil; @@ -140,7 +140,7 @@ void TVMExpressionCompiler::visit2(TupleExpression const &_tupleExpression) { int n = components.size(); if (*_tupleExpression.annotation().isPure) { const int stackSize = m_pusher.stackSize(); - SourceReference sr = SourceReferenceExtractor::extract(*GlobalParams::g_compilerStack, &_tupleExpression.location()); + SourceReference sr = SourceReferenceExtractor::extract(*GlobalParams::g_charStreamProvider, &_tupleExpression.location()); const std::string computeName = "inline_array_line_" + toString(sr.position.line) + "_column_" + toString(sr.position.column) + "_ast_id_" + toString(_tupleExpression.id()); diff --git a/compiler/libsolidity/codegen/TVMFunctionCall.cpp b/compiler/libsolidity/codegen/TVMFunctionCall.cpp index 2784a2ea..f390732b 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCall.cpp +++ b/compiler/libsolidity/codegen/TVMFunctionCall.cpp @@ -27,7 +27,7 @@ #include "TVMExpressionCompiler.hpp" #include "TVMFunctionCall.hpp" #include "TVMStructCompiler.hpp" -#include "TVM.h" +#include "TVM.hpp" using namespace solidity::frontend; using namespace solidity::langutil; @@ -3480,7 +3480,7 @@ void FunctionCallCompiler::creatArrayWithDefaultValue() { if (*m_functionCall.annotation().isPure) { pushArgs(); - SourceReference sr = SourceReferenceExtractor::extract(*GlobalParams::g_compilerStack, &m_functionCall.location()); + SourceReference sr = SourceReferenceExtractor::extract(*GlobalParams::g_charStreamProvider, &m_functionCall.location()); const std::string computeName = "new_array_line_" + toString(sr.position.line) + "_column_" + toString(sr.position.column) + "_ast_id_" + toString(m_functionCall.id()); diff --git a/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp b/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp index cbc1d5d0..f5f52fcd 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp +++ b/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp @@ -29,7 +29,7 @@ #include "TVMFunctionCall.hpp" #include "TVMFunctionCompiler.hpp" #include "TVMStructCompiler.hpp" -#include "TVM.h" +#include "TVM.hpp" using namespace solidity::frontend; using namespace solidity::langutil; @@ -1568,13 +1568,6 @@ bool TVMFunctionCompiler::visit(EmitStatement const &_emit) { return false; } -Pointer TVMFunctionCompiler::generateMainExternal(TVMCompilerContext& ctx, ContractDefinition const *contract) { - StackPusher pusher{&ctx}; - TVMFunctionCompiler funCompiler{pusher, contract}; - Pointer f = funCompiler.generateMainExternalForAbiV2(); - return f; -} - void TVMFunctionCompiler::setGlobSenderAddressIfNeed() { if (m_pusher.ctx().usage().hasMsgSender()) { m_pusher.pushSlice("x8000000000000000000000000000000000000000000000000000000000000000001_"); @@ -1606,42 +1599,48 @@ void TVMFunctionCompiler::setCopyleftAndTryCatch() { } } -Pointer -TVMFunctionCompiler::generateMainExternalForAbiV2() { -// stack: -// contract_balance -// msg_balance is always zero -// msg_cell -// msg_body_slice -// transaction_id = -1 +Pointer TVMFunctionCompiler::generateMainExternal( + TVMCompilerContext& ctx, + ContractDefinition const *contract +) { + // stack: + // contract_balance + // msg_balance is always zero + // msg_cell + // msg_body_slice + // transaction_id = -1 - setCopyleftAndTryCatch(); - setCtorFlag(); // TODO unit with setCopyleftAndTryCatch - setGlobSenderAddressIfNeed(); + StackPusher pusher{&ctx}; + TVMFunctionCompiler f{pusher, contract}; - m_pusher.pushS(1); + f.setCopyleftAndTryCatch(); + f.setCtorFlag(); // TODO unit with setCopyleftAndTryCatch + f.setGlobSenderAddressIfNeed(); - m_pusher.pushMacroCallInCallRef(0, 0, "c4_to_c7_with_init_storage"); + pusher.pushS(1); + pusher.pushMacroCallInCallRef(0, 0, "c4_to_c7_with_init_storage"); - checkSignatureAndReadPublicKey(); - if (m_pusher.ctx().afterSignatureCheck()) { + f.checkSignatureAndReadPublicKey(); + if (pusher.ctx().afterSignatureCheck()) { // ... msg_cell msg_body_slice -1 rest_msg_body_slice - m_pusher.pushS(3); - Pointer block = m_pusher.ctx().getInlinedFunction("afterSignatureCheck"); - m_pusher.pushInlineFunction(block, 2, 1); + pusher.pushS(3); + Pointer block = pusher.ctx().getInlinedFunction("afterSignatureCheck"); + pusher.pushInlineFunction(block, 2, 1); } else { - defaultReplayProtection(); - if (m_pusher.ctx().pragmaHelper().hasExpire()) { - expire(); - } + if (pusher.ctx().pragmaHelper().hasTime()) f.defaultReplayProtection(); + if (pusher.ctx().pragmaHelper().hasExpire()) f.expire(); } // msg_body - m_pusher.push(+1, "LDU 32 ; funcId body"); - m_pusher.exchange(1); + pusher.push(+1, "LDU 32 ; funcId body"); + pusher.exchange(1); - callPublicFunctionOrFallback(); - return createNode(0, 0, "main_external", Function::FunctionType::MainExternal, m_pusher.getBlock()); + f.callPublicFunctionOrFallback(); + return createNode( + 0, 0, "main_external", + Function::FunctionType::MainExternal, + pusher.getBlock() + ); } void TVMFunctionCompiler::pushMsgPubkey() { @@ -1890,7 +1889,7 @@ void TVMFunctionCompiler::updC4IfItNeeds() { } else { // if it's external message than save values for replay protection if (m_pusher.ctx().afterSignatureCheck() == nullptr && - m_pusher.ctx().hasTimeInAbiHeader() && + m_pusher.ctx().pragmaHelper().hasTime() && m_pusher.ctx().notConstantStateVariables().size() >= 2 // just optimization ) { m_pusher.pushS(0); @@ -2021,7 +2020,7 @@ void TVMFunctionCompiler::buildPublicFunctionSelector( } void TVMFunctionCompiler::pushLocation(const ASTNode& node, bool reset) { - SourceReference sr = SourceReferenceExtractor::extract(*GlobalParams::g_compilerStack, &node.location()); + SourceReference sr = SourceReferenceExtractor::extract(*GlobalParams::g_charStreamProvider, &node.location()); const int line = reset ? 0 : sr.position.line + 1; m_pusher.pushLoc(sr.sourceName, line); } diff --git a/compiler/libsolidity/codegen/TVMPusher.cpp b/compiler/libsolidity/codegen/TVMPusher.cpp index 453ac55d..46fa200d 100644 --- a/compiler/libsolidity/codegen/TVMPusher.cpp +++ b/compiler/libsolidity/codegen/TVMPusher.cpp @@ -1643,10 +1643,13 @@ void StackPusher::hardConvert(Type const *leftType, Type const *rightType) { if (lQty > rQty) { auto l = to(leftType); hardConvert(l->valueType(), rightType); + // optional(uint, uint) q = (1, 2); if (l->valueType()->category() == Type::Category::Tuple){ - // optional(uint, uint) q = (1, 2); - auto tt = to(l->valueType()); - tuple(tt->components().size()); + if (rightType->category() != Type::Category::Null) { + auto tt = to(l->valueType()); + tuple(tt->components().size()); + } + // optional([mapping|optional]) q = ... } else if (optValueAsTuple(l->valueType())) { tuple(1); } @@ -1819,9 +1822,9 @@ void StackPusher::hardConvert(Type const *leftType, Type const *rightType) { } } }; - - - + + + switch (rightType->category()) { case Type::Category::RationalNumber: { @@ -2549,10 +2552,6 @@ PragmaDirectiveHelper const &TVMCompilerContext::pragmaHelper() const { return m_pragmaHelper; } -bool TVMCompilerContext::hasTimeInAbiHeader() const { - return m_pragmaHelper.hasTime() || afterSignatureCheck() == nullptr; -} - bool TVMCompilerContext::isStdlib() const { return m_contract->name() == "stdlib"; } @@ -2621,7 +2620,7 @@ FunctionDefinition const *TVMCompilerContext::afterSignatureCheck() const { } bool TVMCompilerContext::storeTimestampInC4() const { - return hasTimeInAbiHeader() && afterSignatureCheck() == nullptr; + return m_pragmaHelper.hasTime() && afterSignatureCheck() == nullptr; } int TVMCompilerContext::getOffsetC4() const { diff --git a/compiler/libsolidity/codegen/TVMTypeChecker.cpp b/compiler/libsolidity/codegen/TVMTypeChecker.cpp index c6e3cdb4..e4ba3155 100644 --- a/compiler/libsolidity/codegen/TVMTypeChecker.cpp +++ b/compiler/libsolidity/codegen/TVMTypeChecker.cpp @@ -20,6 +20,7 @@ #include +#include "TVM.hpp" #include "TVMCommons.hpp" #include "TVMConstants.hpp" #include "TVMTypeChecker.hpp" @@ -29,6 +30,10 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace std; +namespace { + string isNotSupportedVM = " is not supported by the VM version. See \"--tvm-version\" command-line option."; +} + TVMTypeChecker::TVMTypeChecker(langutil::ErrorReporter& _errorReporter) : m_errorReporter{_errorReporter} { @@ -243,6 +248,77 @@ bool TVMTypeChecker::visit(IndexRangeAccess const& indexRangeAccess) { return true; } +bool TVMTypeChecker::visit(FunctionCall const& _functionCall) { + Type const* expressionType = _functionCall.expression().annotation().type; + switch (expressionType->category()) { + case Type::Category::Function: { + auto functionType = to(expressionType); + switch (functionType->kind()) { + case FunctionType::Kind::TVMInitCodeHash: + if (*GlobalParams::g_tvmVersion == TVMVersion::ton()) { + m_errorReporter.typeError(228_error, _functionCall.location(), + "\"tvm.initCodeHash()\"" + isNotSupportedVM); + } + break; + case FunctionType::Kind::TVMCode: + if (*GlobalParams::g_tvmVersion == TVMVersion::ton()) { + m_errorReporter.typeError(228_error, _functionCall.location(), + "\"tvm.code()\"" + isNotSupportedVM); + } + break; + default: + break; + } + break; + } + default: + break; + } + + + if (_functionCall.isAwait() && *GlobalParams::g_tvmVersion == TVMVersion::ton()) { + m_errorReporter.typeError(228_error, _functionCall.location(), + "\"*.await\"" + isNotSupportedVM); + } + + return true; +} + +bool TVMTypeChecker::visit(PragmaDirective const& _pragma) { + if (!_pragma.literals().empty()) { + if (_pragma.literals().at(0) == "copyleft" && *GlobalParams::g_tvmVersion == TVMVersion::ton()) { + m_errorReporter.typeError(228_error, _pragma.location(), + "\"pragma copyleft ...\"" + isNotSupportedVM); + } + } + return true; +} + +bool TVMTypeChecker::visit(MemberAccess const& _memberAccess) { + ASTString const& member = _memberAccess.memberName(); + Expression const& expression = _memberAccess.expression(); + switch (expression.annotation().type->category()) { + case Type::Category::Magic: { + if (member == "storageFee") { + if (*GlobalParams::g_tvmVersion == TVMVersion::ton()) { + m_errorReporter.typeError(228_error, _memberAccess.location(), + "\"tx.storageFee\"" + isNotSupportedVM); + } + } + if (auto ident = to(&expression)) { + if (ident->name() == "gosh" && *GlobalParams::g_tvmVersion != TVMVersion::gosh()) { + m_errorReporter.typeError(228_error, _memberAccess.location(), + "\"gosh." + member + "\"" + isNotSupportedVM); + } + } + break; + } + default: + break; + } + return true; +} + bool TVMTypeChecker::visit(ContractDefinition const& cd) { contractDefinition = &cd; diff --git a/compiler/libsolidity/codegen/TVMTypeChecker.hpp b/compiler/libsolidity/codegen/TVMTypeChecker.hpp index e48344fc..1f6dcaf5 100644 --- a/compiler/libsolidity/codegen/TVMTypeChecker.hpp +++ b/compiler/libsolidity/codegen/TVMTypeChecker.hpp @@ -33,6 +33,9 @@ class TVMTypeChecker : public ASTConstVisitor { bool visit(FunctionDefinition const& fc) override; bool visit(ContractDefinition const& ) override; bool visit(IndexRangeAccess const& ) override; + bool visit(FunctionCall const& ) override; + bool visit(PragmaDirective const& ) override; + bool visit(MemberAccess const& ) override; void endVisit(ContractDefinition const& ) override; private: diff --git a/compiler/libsolidity/codegen/TvmAst.cpp b/compiler/libsolidity/codegen/TvmAst.cpp index 447c9c62..d8d8ac24 100644 --- a/compiler/libsolidity/codegen/TvmAst.cpp +++ b/compiler/libsolidity/codegen/TvmAst.cpp @@ -21,12 +21,14 @@ #include -#include "TvmAst.hpp" -#include "TvmAstVisitor.hpp" +#include + +#include "TVM.hpp" #include "TVMCommons.hpp" -#include "TVMPusher.hpp" #include "TVMConstants.hpp" -#include +#include "TVMPusher.hpp" +#include "TvmAst.hpp" +#include "TvmAstVisitor.hpp" using namespace solidity::frontend; using namespace std; @@ -133,6 +135,13 @@ bool AsymGen::operator==(TvmAstNode const& _node) const { return a && opcode() == a->opcode(); } +AsymGen::AsymGen(std::string opcode) : + m_opcode(std::move(opcode)) +{ + if (boost::starts_with(m_opcode, "ZERO")) + solAssert(*GlobalParams::g_tvmVersion != langutil::TVMVersion::ton(), ""); +} + void HardCode::accept(TvmAstVisitor& _visitor) { _visitor.visit(*this); } @@ -454,6 +463,9 @@ Pointer gen(const std::string& cmd) { iss >> op >> param; } + if (*GlobalParams::g_tvmVersion == langutil::TVMVersion::ton()) + solAssert(!isIn(op, "COPYLEFT", "INITCODEHASH", "MYCODE", "LDCONT", "STCONT"), ""); + auto f = [&](const std::string& pattert) { return op == pattert; }; diff --git a/compiler/libsolidity/codegen/TvmAst.hpp b/compiler/libsolidity/codegen/TvmAst.hpp index 40b857cf..9102c05b 100644 --- a/compiler/libsolidity/codegen/TvmAst.hpp +++ b/compiler/libsolidity/codegen/TvmAst.hpp @@ -157,8 +157,7 @@ namespace solidity::frontend class AsymGen : public TvmAstNode { public: - explicit AsymGen(std::string opcode) : - m_opcode(std::move(opcode)){} + explicit AsymGen(std::string opcode); void accept(TvmAstVisitor& _visitor) override; bool operator==(TvmAstNode const&) const override; std::string const& opcode() const { return m_opcode; } diff --git a/compiler/libsolidity/interface/CompilerStack.cpp b/compiler/libsolidity/interface/CompilerStack.cpp index 441c7d4b..e566cce4 100644 --- a/compiler/libsolidity/interface/CompilerStack.cpp +++ b/compiler/libsolidity/interface/CompilerStack.cpp @@ -76,7 +76,7 @@ #include #include -#include +#include #include #include #include @@ -108,7 +108,7 @@ CompilerStack::CompilerStack(ReadCallback::Callback _readFile): solAssert(g_compilerStackCounts == 0, "You shall not have another CompilerStack aside me."); ++g_compilerStackCounts; GlobalParams::g_errorReporter = &m_errorReporter; - GlobalParams::g_compilerStack = this; + GlobalParams::g_charStreamProvider = this; } CompilerStack::~CompilerStack() @@ -228,6 +228,15 @@ void CompilerStack::setEVMVersion(langutil::EVMVersion _version) m_evmVersion = _version; } +void CompilerStack::setTVMVersion(langutil::TVMVersion _version) +{ + if (m_stackState >= ParsedAndImported) + solThrow(CompilerError, "Must set TVM version before parsing."); + m_tvmVersion = _version; + + GlobalParams::g_tvmVersion = m_tvmVersion; +} + void CompilerStack::setLibraries(std::map const& _libraries) { if (m_stackState >= ParsedAndImported) diff --git a/compiler/libsolidity/interface/CompilerStack.h b/compiler/libsolidity/interface/CompilerStack.h index 67571d6b..fbbb94b5 100644 --- a/compiler/libsolidity/interface/CompilerStack.h +++ b/compiler/libsolidity/interface/CompilerStack.h @@ -35,9 +35,10 @@ #include #include -#include #include +#include #include +#include #include #include @@ -163,6 +164,8 @@ class CompilerStack: public langutil::CharStreamProvider /// Must be set before parsing. void setEVMVersion(langutil::EVMVersion _version = langutil::EVMVersion{}); + void setTVMVersion(langutil::TVMVersion _version = langutil::TVMVersion{}); + /// Sets the requested contract names by source. /// If empty, no filtering is performed and every contract /// found in the supplied sources is compiled. @@ -491,6 +494,7 @@ class CompilerStack: public langutil::CharStreamProvider std::string m_inputFile; bool m_doPrintFunctionIds = false; bool m_doPrivateFunctionIds = false; + solidity::langutil::TVMVersion m_tvmVersion; }; } diff --git a/compiler/libsolidity/interface/StandardCompiler.cpp b/compiler/libsolidity/interface/StandardCompiler.cpp index 73608183..378ac4a3 100644 --- a/compiler/libsolidity/interface/StandardCompiler.cpp +++ b/compiler/libsolidity/interface/StandardCompiler.cpp @@ -366,7 +366,7 @@ std::optional checkAuxiliaryInputKeys(Json::Value const& _input) std::optional checkSettingsKeys(Json::Value const& _input) { static set keys{"parserErrorRecovery", "debug", "evmVersion", "libraries", "metadata", "optimizer", "outputSelection", "remappings", - "includePaths", "mainContract"}; + "includePaths", "mainContract", "tvmVersion"}; return checkKeys(_input, keys, "settings"); } @@ -727,6 +727,16 @@ std::variant StandardCompiler: ret.evmVersion = *version; } + if (settings.isMember("tvmVersion")) + { + if (!settings["tvmVersion"].isString()) + return formatFatalError("JSONError", "tvmVersion must be a string."); + std::optional version = langutil::TVMVersion::fromString(settings["tvmVersion"].asString()); + if (!version) + return formatFatalError("JSONError", "Invalid TVM version requested."); + ret.tvmVersion = *version; + } + if (settings.isMember("debug")) { if (auto result = checkKeys(settings["debug"], {"revertStrings", "debugInfo"}, "settings.debug")) @@ -982,6 +992,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting compilerStack.setSources(sourceList); // TODO: do we need EVMVersion and other stuff? compilerStack.setEVMVersion(_inputsAndSettings.evmVersion); + compilerStack.setTVMVersion(_inputsAndSettings.tvmVersion); compilerStack.setParserErrorRecovery(_inputsAndSettings.parserErrorRecovery); compilerStack.setRemappings(std::move(_inputsAndSettings.remappings)); compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings)); diff --git a/compiler/libsolidity/interface/StandardCompiler.h b/compiler/libsolidity/interface/StandardCompiler.h index 1c52ebf7..678cb578 100644 --- a/compiler/libsolidity/interface/StandardCompiler.h +++ b/compiler/libsolidity/interface/StandardCompiler.h @@ -75,6 +75,7 @@ class StandardCompiler std::map sources; std::map smtLib2Responses; langutil::EVMVersion evmVersion; + langutil::TVMVersion tvmVersion; std::vector remappings; RevertStrings revertStrings = RevertStrings::Default; OptimiserSettings optimiserSettings = OptimiserSettings::minimal(); diff --git a/compiler/solc/CommandLineInterface.cpp b/compiler/solc/CommandLineInterface.cpp index c8f31c3a..a15c0f9b 100644 --- a/compiler/solc/CommandLineInterface.cpp +++ b/compiler/solc/CommandLineInterface.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -506,6 +505,7 @@ void CommandLineInterface::compile() if (m_options.tvmParams.printPrivateFunctionIds) m_compiler->printPrivateFunctionIds(); m_compiler->setOutputFolder(m_options.output.dir.string()); + m_compiler->setTVMVersion(m_options.tvmParams.tvmVersion); bool successful = true; bool didCompileSomething = false; diff --git a/compiler/solc/CommandLineParser.cpp b/compiler/solc/CommandLineParser.cpp index 0e35cf7c..46e87423 100644 --- a/compiler/solc/CommandLineParser.cpp +++ b/compiler/solc/CommandLineParser.cpp @@ -21,6 +21,7 @@ #include #include +#include #include @@ -87,6 +88,7 @@ static string const g_strAsm = "asm"; static string const g_strABI = "abi-json"; static string const g_strFunctionIds = "function-ids"; static string const g_strPrivateFunctionIds = "private-function-ids"; +static string const g_strTVMVersion = "tvm-version"; /// Possible arguments to for --revert-strings @@ -576,6 +578,11 @@ General Information)").c_str(), po::value()->value_name("path"), "Output directory (by default, current directory is used)" ) + ( + g_strTVMVersion.c_str(), + po::value()->value_name("version")->default_value(TVMVersion{}.name()), + "Select desired TVM version. Either ever, ton, gosh." + ) ; desc.add(outputOptions); @@ -938,6 +945,15 @@ void CommandLineParser::processArgs() solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport); + if (m_args.count(g_strTVMVersion)) + { + string versionOptionStr = m_args[g_strTVMVersion].as(); + std::optional versionOption = langutil::TVMVersion::fromString(versionOptionStr); + if (!versionOption) + solThrow(CommandLineValidationError, "Invalid option for --" + g_strTVMVersion + ": " + versionOptionStr); + m_options.tvmParams.tvmVersion = *versionOption; + } + if (m_args.count(g_strContract)) m_options.tvmParams.mainContract = m_args[g_strContract].as(); if (m_args.count(g_strOutputPrefix)) diff --git a/compiler/solc/CommandLineParser.h b/compiler/solc/CommandLineParser.h index e56a159b..f4310a06 100644 --- a/compiler/solc/CommandLineParser.h +++ b/compiler/solc/CommandLineParser.h @@ -27,6 +27,7 @@ #include #include +#include #include @@ -228,6 +229,7 @@ struct CommandLineOptions bool abi = false; bool printFunctionIds = false; bool printPrivateFunctionIds = false; + langutil::TVMVersion tvmVersion; } tvmParams; }; diff --git a/sold/Cargo.toml b/sold/Cargo.toml index ce7144ff..4e98ba1d 100644 --- a/sold/Cargo.toml +++ b/sold/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = '2021' name = 'sold' -version = '0.68.0' +version = '0.69.0' [[bin]] name = 'sold' diff --git a/sold/src/lib.rs b/sold/src/lib.rs index 359e3e0c..2b1ef4bc 100644 --- a/sold/src/lib.rs +++ b/sold/src/lib.rs @@ -1,9 +1,10 @@ +use std::fmt; use std::fs::File; use std::io::Write; use std::os::raw::{c_char, c_void}; use std::path::Path; -use clap::Parser; +use clap::{ValueEnum, Parser}; use failure::{bail, format_err}; use serde::Deserialize; @@ -107,12 +108,21 @@ fn compile(args: &Args, input: &str, remappings: Vec) -> Result<(String, } else { "" }; + let tvm_version = match args.tvm_version { + None => { + "".to_string() + } + Some(version) => { + format!(r#""tvmVersion": "{}","#, version) + } + }; let main_contract = args.contract.clone().unwrap_or_default(); let remappings = remappings_to_json_string(remappings); let input_json = format!(r#" {{ "language": "Solidity", "settings": {{ + {tvm_version} "mainContract": "{main_contract}", "remappings": {remappings}, "outputSelection": {{ @@ -347,7 +357,7 @@ pub fn build(args: Args) -> Status { .ok_or_else(|| parse_error!())?; array.push(ast.clone()); } - assert!(array.len() == 1); + assert_eq!(array.len(), 1); println!("{}", serde_json::to_string(&array[0])?); return Ok(()) } @@ -422,6 +432,23 @@ pub fn build(args: Args) -> Status { use once_cell::sync::OnceCell; pub static VERSION: OnceCell = OnceCell::new(); +#[derive(Copy, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] +pub enum TvmVersion { + Ton, + Ever, + Gosh, +} + +impl fmt::Display for TvmVersion { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + TvmVersion::Ton => write!(f, "ton"), + TvmVersion::Ever => write!(f, "ever"), + TvmVersion::Gosh => write!(f, "gosh"), + } + } +} + #[derive(Parser, Debug)] #[clap(author, about = "sold, the Ever Solidity commandline driver", long_about = None)] #[clap(arg_required_else_help = true)] @@ -459,6 +486,9 @@ pub struct Args { /// Output directory (by default, current directory is used) #[clap(short('o'), long, value_parser, value_names = &["PATH"])] pub output_dir: Option, + /// Select desired TVM version. + #[clap(long, value_enum)] + pub tvm_version: Option, //Output Components: /// Print the code cell to stdout