We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
2 parents 86e4bba + 9242939 commit 728ecd6Copy full SHA for 728ecd6
Changelog.md
@@ -1,6 +1,7 @@
1
### 0.8.31 (unreleased)
2
3
Language Features:
4
+* Yul: Introduce builtin `clz(x)` for counting the number of leading zero bits in a 256-bit word.
5
6
Compiler Features:
7
* ethdebug: Experimental support for instructions and source locations under EOF.
docs/grammar/SolidityLexer.g4
@@ -300,7 +300,7 @@ YulHex: 'hex';
300
YulEVMBuiltin:
301
'stop' | 'add' | 'sub' | 'mul' | 'div' | 'sdiv' | 'mod' | 'smod' | 'exp' | 'not'
302
| 'lt' | 'gt' | 'slt' | 'sgt' | 'eq' | 'iszero' | 'and' | 'or' | 'xor' | 'byte'
303
- | 'shl' | 'shr' | 'sar' | 'addmod' | 'mulmod' | 'signextend' | 'keccak256'
+ | 'shl' | 'shr' | 'sar' | 'clz' | 'addmod' | 'mulmod' | 'signextend' | 'keccak256'
304
| 'pop' | 'mload' | 'mstore' | 'mstore8' | 'sload' | 'sstore' | 'tload' | 'tstore'| 'msize' | 'gas'
305
| 'address' | 'balance' | 'selfbalance' | 'caller' | 'callvalue' | 'calldataload'
306
| 'calldatasize' | 'calldatacopy' | 'extcodesize' | 'extcodecopy' | 'returndatasize'
docs/yul.rst
@@ -752,8 +752,8 @@ This document does not want to be a full description of the Ethereum virtual mac
752
Please refer to a different document if you are interested in the precise semantics.
753
754
Opcodes marked with ``-`` do not return a result and all others return exactly one value.
755
-Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P`` and ``N`` are present since Frontier,
756
-Homestead, Byzantium, Constantinople, Istanbul, London, Paris or Cancun respectively.
+Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P``, ``N`` and ``O`` are present since
+Frontier, Homestead, Byzantium, Constantinople, Istanbul, London, Paris, Cancun or Osaka respectively.
757
758
In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to
759
but not including position ``b``, ``storage[p]`` signifies the storage contents at slot ``p``, and
@@ -812,6 +812,8 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a
812
+-------------------------+-----+---+-----------------------------------------------------------------+
813
| sar(x, y) | | C | signed arithmetic shift right y by x bits |
814
815
+| clz(x) | | O | number of leading zero bits of x, 256 if x == 0 |
816
++-------------------------+-----+---+-----------------------------------------------------------------+
817
| addmod(x, y, m) | | F | (x + y) % m with arbitrary precision arithmetic, 0 if m == 0 |
818
819
| mulmod(x, y, m) | | F | (x * y) % m with arbitrary precision arithmetic, 0 if m == 0 |
libevmasm/Instruction.cpp
@@ -51,6 +51,7 @@ std::map<std::string, Instruction, std::less<>> const solidity::evmasm::c_instru
51
{ "SHL", Instruction::SHL },
52
{ "SHR", Instruction::SHR },
53
{ "SAR", Instruction::SAR },
54
+ { "CLZ", Instruction::CLZ },
55
{ "ADDMOD", Instruction::ADDMOD },
56
{ "MULMOD", Instruction::MULMOD },
57
{ "SIGNEXTEND", Instruction::SIGNEXTEND },
@@ -219,6 +220,7 @@ static std::map<Instruction, InstructionInfo> const c_instructionInfo =
219
220
{Instruction::SHL, {"SHL", 0, 2, 1, false, Tier::VeryLow}},
221
{Instruction::SHR, {"SHR", 0, 2, 1, false, Tier::VeryLow}},
222
{Instruction::SAR, {"SAR", 0, 2, 1, false, Tier::VeryLow}},
223
+ {Instruction::CLZ, {"CLZ", 0, 1, 1, false, Tier::Low}},
224
{Instruction::ADDMOD, {"ADDMOD", 0, 3, 1, false, Tier::Mid}},
225
{Instruction::MULMOD, {"MULMOD", 0, 3, 1, false, Tier::Mid}},
226
{Instruction::SIGNEXTEND, {"SIGNEXTEND", 0, 2, 1, false, Tier::Low}},
libevmasm/Instruction.h
@@ -61,6 +61,7 @@ enum class Instruction: uint8_t
61
SHL, ///< bitwise SHL operation
62
SHR, ///< bitwise SHR operation
63
SAR, ///< bitwise SAR operation
64
+ CLZ, ///< count of leading zeros in binary representation
65
66
KECCAK256 = 0x20, ///< compute KECCAK-256 hash
67
libevmasm/SimplificationRule.h
@@ -98,6 +98,7 @@ struct EVMBuiltins
98
static auto constexpr SHL = PatternGenerator<Instruction::SHL>{};
99
static auto constexpr SHR = PatternGenerator<Instruction::SHR>{};
100
static auto constexpr SAR = PatternGenerator<Instruction::SAR>{};
101
+ static auto constexpr CLZ = PatternGenerator<Instruction::CLZ>{};
102
static auto constexpr ADDMOD = PatternGenerator<Instruction::ADDMOD>{};
103
static auto constexpr MULMOD = PatternGenerator<Instruction::MULMOD>{};
104
static auto constexpr SIGNEXTEND = PatternGenerator<Instruction::SIGNEXTEND>{};
liblangutil/EVMVersion.cpp
@@ -42,6 +42,8 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional<uint8_t> _eofVersi
42
case Instruction::SHR:
43
case Instruction::SAR:
44
return hasBitwiseShifting();
45
+ case Instruction::CLZ:
46
+ return hasCLZ();
47
case Instruction::CREATE2:
48
return !_eofVersion.has_value() && hasCreate2();
49
case Instruction::EXTCODEHASH:
liblangutil/EVMVersion.h
@@ -133,6 +133,7 @@ class EVMVersion
133
bool supportsReturndata() const { return *this >= byzantium(); }
134
bool hasStaticCall() const { return *this >= byzantium(); }
135
bool hasBitwiseShifting() const { return *this >= constantinople(); }
136
+ bool hasCLZ() const { return *this >= osaka(); }
137
bool hasCreate2() const { return *this >= constantinople(); }
138
bool hasExtCodeHash() const { return *this >= constantinople(); }
139
bool hasChainID() const { return *this >= istanbul(); }
libyul/AsmAnalysis.cpp
@@ -834,6 +834,8 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
834
errorForVM(7458_error, "only available for Constantinople-compatible");
835
else if (_instr == evmasm::Instruction::SAR && !m_evmVersion.hasBitwiseShifting())
836
errorForVM(2054_error, "only available for Constantinople-compatible");
837
+ else if (_instr == evmasm::Instruction::CLZ && !m_evmVersion.hasCLZ())
838
+ errorForVM(4948_error, "only available for Osaka-compatible");
839
else if (_instr == evmasm::Instruction::CREATE2 && !m_evmVersion.hasCreate2())
840
errorForVM(6166_error, "only available for Constantinople-compatible");
841
else if (_instr == evmasm::Instruction::EXTCODEHASH && !m_evmVersion.hasExtCodeHash())
libyul/backends/evm/EVMDialect.cpp
@@ -132,6 +132,12 @@ std::set<std::string, std::less<>> createReservedIdentifiers(langutil::EVMVersio
132
_evmVersion < langutil::EVMVersion::cancun() &&
(_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD);
};
+ // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name
+ // clz for VMs before osaka.
+ auto clzException = [&](evmasm::Instruction _instr) -> bool
+ {
+ return _instr == evmasm::Instruction::CLZ && !_evmVersion.hasCLZ();
140
+ };
141
142
auto eofIdentifiersException = [&](evmasm::Instruction _instr) -> bool
143
{
@@ -154,6 +160,7 @@ std::set<std::string, std::less<>> createReservedIdentifiers(langutil::EVMVersio
154
160
!blobBaseFeeException(instr.second) &&
155
161
!mcopyException(instr.second) &&
156
162
!transientStorageException(instr.second) &&
163
+ !clzException(instr.second) &&
157
164
!eofIdentifiersException(instr.second)
158
165
)
159
166
reserved.emplace(name);
0 commit comments