Skip to content

Commit 779daec

Browse files
add CLZ to YUL build-in instruction for Osaka
1 parent 406bdfb commit 779daec

File tree

20 files changed

+153
-3
lines changed

20 files changed

+153
-3
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
### 0.8.31 (unreleased)
22

33
Language Features:
4+
* Yul: Introduce builtin ``clz(x)`` for counting leading zeoros.
45

56
Compiler Features:
67
* ethdebug: Experimental support for instructions and source locations under EOF.

docs/grammar/SolidityLexer.g4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ YulHex: 'hex';
300300
YulEVMBuiltin:
301301
'stop' | 'add' | 'sub' | 'mul' | 'div' | 'sdiv' | 'mod' | 'smod' | 'exp' | 'not'
302302
| 'lt' | 'gt' | 'slt' | 'sgt' | 'eq' | 'iszero' | 'and' | 'or' | 'xor' | 'byte'
303-
| 'shl' | 'shr' | 'sar' | 'addmod' | 'mulmod' | 'signextend' | 'keccak256'
303+
| 'shl' | 'shr' | 'sar' | 'clz' | 'addmod' | 'mulmod' | 'signextend' | 'keccak256'
304304
| 'pop' | 'mload' | 'mstore' | 'mstore8' | 'sload' | 'sstore' | 'tload' | 'tstore'| 'msize' | 'gas'
305305
| 'address' | 'balance' | 'selfbalance' | 'caller' | 'callvalue' | 'calldataload'
306306
| 'calldatasize' | 'calldatacopy' | 'extcodesize' | 'extcodecopy' | 'returndatasize'

docs/yul.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,8 +752,8 @@ This document does not want to be a full description of the Ethereum virtual mac
752752
Please refer to a different document if you are interested in the precise semantics.
753753

754754
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.
755+
Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P``, ``N``, ``R`` and ``O`` are present since
756+
Frontier, Homestead, Byzantium, Constantinople, Istanbul, London, Paris, Cancun, Prague or Osaka respectively.
757757

758758
In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to
759759
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
812812
+-------------------------+-----+---+-----------------------------------------------------------------+
813813
| sar(x, y) | | C | signed arithmetic shift right y by x bits |
814814
+-------------------------+-----+---+-----------------------------------------------------------------+
815+
| clz(x) | | O | leading zeros of x in binary representation, 256 if x == 0 |
816+
+-------------------------+-----+---+-----------------------------------------------------------------+
815817
| addmod(x, y, m) | | F | (x + y) % m with arbitrary precision arithmetic, 0 if m == 0 |
816818
+-------------------------+-----+---+-----------------------------------------------------------------+
817819
| mulmod(x, y, m) | | F | (x * y) % m with arbitrary precision arithmetic, 0 if m == 0 |

libevmasm/Instruction.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ std::map<std::string, Instruction, std::less<>> const solidity::evmasm::c_instru
5151
{ "SHL", Instruction::SHL },
5252
{ "SHR", Instruction::SHR },
5353
{ "SAR", Instruction::SAR },
54+
{ "CLZ", Instruction::CLZ },
5455
{ "ADDMOD", Instruction::ADDMOD },
5556
{ "MULMOD", Instruction::MULMOD },
5657
{ "SIGNEXTEND", Instruction::SIGNEXTEND },
@@ -219,6 +220,7 @@ static std::map<Instruction, InstructionInfo> const c_instructionInfo =
219220
{Instruction::SHL, {"SHL", 0, 2, 1, false, Tier::VeryLow}},
220221
{Instruction::SHR, {"SHR", 0, 2, 1, false, Tier::VeryLow}},
221222
{Instruction::SAR, {"SAR", 0, 2, 1, false, Tier::VeryLow}},
223+
{Instruction::CLZ, {"CLZ", 0, 1, 1, false, Tier::Low}},
222224
{Instruction::ADDMOD, {"ADDMOD", 0, 3, 1, false, Tier::Mid}},
223225
{Instruction::MULMOD, {"MULMOD", 0, 3, 1, false, Tier::Mid}},
224226
{Instruction::SIGNEXTEND, {"SIGNEXTEND", 0, 2, 1, false, Tier::Low}},

libevmasm/Instruction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ enum class Instruction: uint8_t
6161
SHL, ///< bitwise SHL operation
6262
SHR, ///< bitwise SHR operation
6363
SAR, ///< bitwise SAR operation
64+
CLZ, ///< count of leading zeros in binary representation
6465

6566
KECCAK256 = 0x20, ///< compute KECCAK-256 hash
6667

libevmasm/SimplificationRule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct EVMBuiltins
9898
static auto constexpr SHL = PatternGenerator<Instruction::SHL>{};
9999
static auto constexpr SHR = PatternGenerator<Instruction::SHR>{};
100100
static auto constexpr SAR = PatternGenerator<Instruction::SAR>{};
101+
static auto constexpr CLZ = PatternGenerator<Instruction::CLZ>{};
101102
static auto constexpr ADDMOD = PatternGenerator<Instruction::ADDMOD>{};
102103
static auto constexpr MULMOD = PatternGenerator<Instruction::MULMOD>{};
103104
static auto constexpr SIGNEXTEND = PatternGenerator<Instruction::SIGNEXTEND>{};

liblangutil/EVMVersion.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional<uint8_t> _eofVersi
4242
case Instruction::SHR:
4343
case Instruction::SAR:
4444
return hasBitwiseShifting();
45+
case Instruction::CLZ:
46+
return hasCLZ();
4547
case Instruction::CREATE2:
4648
return !_eofVersion.has_value() && hasCreate2();
4749
case Instruction::EXTCODEHASH:

liblangutil/EVMVersion.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class EVMVersion:
128128
bool supportsReturndata() const { return *this >= byzantium(); }
129129
bool hasStaticCall() const { return *this >= byzantium(); }
130130
bool hasBitwiseShifting() const { return *this >= constantinople(); }
131+
bool hasCLZ() const { return *this >= osaka(); }
131132
bool hasCreate2() const { return *this >= constantinople(); }
132133
bool hasExtCodeHash() const { return *this >= constantinople(); }
133134
bool hasChainID() const { return *this >= istanbul(); }

libyul/AsmAnalysis.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,8 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
834834
errorForVM(7458_error, "only available for Constantinople-compatible");
835835
else if (_instr == evmasm::Instruction::SAR && !m_evmVersion.hasBitwiseShifting())
836836
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");
837839
else if (_instr == evmasm::Instruction::CREATE2 && !m_evmVersion.hasCreate2())
838840
errorForVM(6166_error, "only available for Constantinople-compatible");
839841
else if (_instr == evmasm::Instruction::EXTCODEHASH && !m_evmVersion.hasExtCodeHash())

libyul/backends/evm/EVMDialect.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ std::set<std::string, std::less<>> createReservedIdentifiers(langutil::EVMVersio
152152
_evmVersion < langutil::EVMVersion::cancun() &&
153153
(_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD);
154154
};
155+
// TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name
156+
// clz for VMs before osaka.
157+
auto clzException = [&](evmasm::Instruction _instr) -> bool
158+
{
159+
return _instr == evmasm::Instruction::CLZ && _evmVersion < langutil::EVMVersion::osaka();
160+
};
155161

156162
auto eofIdentifiersException = [&](evmasm::Instruction _instr) -> bool
157163
{
@@ -174,6 +180,7 @@ std::set<std::string, std::less<>> createReservedIdentifiers(langutil::EVMVersio
174180
!blobBaseFeeException(instr.second) &&
175181
!mcopyException(instr.second) &&
176182
!transientStorageException(instr.second) &&
183+
!clzException(instr.second) &&
177184
!eofIdentifiersException(instr.second)
178185
)
179186
reserved.emplace(name);

0 commit comments

Comments
 (0)