mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9367 from ethereum/wasm-dialect
Add ctz and popcnt to WasmDialect
This commit is contained in:
commit
1d666335f8
@ -1,5 +1,8 @@
|
||||
### 0.6.12 (unreleased)
|
||||
|
||||
Language Features:
|
||||
* Wasm backend: Add ``i32.ctz``, ``i64.ctz``, ``i32.popcnt``, and ``i64.popcnt``.
|
||||
|
||||
Compiler Features:
|
||||
* Code Generator: Evaluate ``keccak256`` of string literals at compile-time.
|
||||
|
||||
|
@ -38,13 +38,18 @@ WasmDialect::WasmDialect()
|
||||
"add",
|
||||
"sub",
|
||||
"mul",
|
||||
// TODO: div_s
|
||||
"div_u",
|
||||
// TODO: rem_s
|
||||
"rem_u",
|
||||
"and",
|
||||
"or",
|
||||
"xor",
|
||||
"shl",
|
||||
// TODO: shr_s
|
||||
"shr_u",
|
||||
// TODO: rotl
|
||||
// TODO: rotr
|
||||
})
|
||||
addFunction(t.str() + "." + name, {t, t}, {t});
|
||||
|
||||
@ -52,9 +57,13 @@ WasmDialect::WasmDialect()
|
||||
for (auto const& name: {
|
||||
"eq",
|
||||
"ne",
|
||||
// TODO: lt_s
|
||||
"lt_u",
|
||||
// TODO: gt_s
|
||||
"gt_u",
|
||||
// TODO: le_s
|
||||
"le_u",
|
||||
// TODO: ge_s
|
||||
"ge_u"
|
||||
})
|
||||
addFunction(t.str() + "." + name, {t, t}, {i32});
|
||||
@ -62,8 +71,13 @@ WasmDialect::WasmDialect()
|
||||
addFunction("i32.eqz", {i32}, {i32});
|
||||
addFunction("i64.eqz", {i64}, {i32});
|
||||
|
||||
addFunction("i32.clz", {i32}, {i32});
|
||||
addFunction("i64.clz", {i64}, {i64});
|
||||
for (auto t: types)
|
||||
for (auto const& name: {
|
||||
"clz",
|
||||
"ctz",
|
||||
"popcnt",
|
||||
})
|
||||
addFunction(t.str() + "." + name, {t}, {t});
|
||||
|
||||
addFunction("i32.wrap_i64", {i64}, {i32});
|
||||
|
||||
@ -73,6 +87,7 @@ WasmDialect::WasmDialect()
|
||||
m_functions["i32.store"_yulstring].sideEffects.invalidatesStorage = false;
|
||||
addFunction("i64.store", {i32, i64}, {}, false);
|
||||
m_functions["i64.store"_yulstring].sideEffects.invalidatesStorage = false;
|
||||
// TODO: add i32.store16, i64.store8, i64.store16, i64.store32
|
||||
|
||||
addFunction("i32.store8", {i32, i32}, {}, false);
|
||||
m_functions["i32.store8"_yulstring].sideEffects.invalidatesStorage = false;
|
||||
@ -89,6 +104,7 @@ WasmDialect::WasmDialect()
|
||||
m_functions["i64.load"_yulstring].sideEffects.invalidatesMemory = false;
|
||||
m_functions["i64.load"_yulstring].sideEffects.sideEffectFree = true;
|
||||
m_functions["i64.load"_yulstring].sideEffects.sideEffectFreeIfNoMSize = true;
|
||||
// TODO: add i32.load8, i32.load16, i64.load8, i64.load16, i64.load32
|
||||
|
||||
// Drop is actually overloaded for all types, but Yul does not support that.
|
||||
// Because of that, we introduce "i32.drop" and "i64.drop".
|
||||
|
@ -67,6 +67,50 @@ uint64_t clz64(uint64_t _v)
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Count trailing zeros for uint32. Following WebAssembly rules, it returns 32 for @a _v being zero.
|
||||
/// NOTE: the ctz builtin of the compiler may or may not do this
|
||||
uint32_t ctz32(uint32_t _v)
|
||||
{
|
||||
if (_v == 0)
|
||||
return 32;
|
||||
|
||||
uint32_t r = 0;
|
||||
while (!(_v & 1))
|
||||
{
|
||||
r++;
|
||||
_v >>= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Count trailing zeros for uint64. Following WebAssembly rules, it returns 64 for @a _v being zero.
|
||||
/// NOTE: the ctz builtin of the compiler may or may not do this
|
||||
uint64_t ctz64(uint64_t _v)
|
||||
{
|
||||
if (_v == 0)
|
||||
return 64;
|
||||
|
||||
uint64_t r = 0;
|
||||
while (!(_v & 1))
|
||||
{
|
||||
r++;
|
||||
_v >>= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Count number of bits set for uint64
|
||||
uint64_t popcnt(uint64_t _v)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
while (_v)
|
||||
{
|
||||
r += (_v & 1);
|
||||
_v >>= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
|
||||
@ -139,6 +183,10 @@ u256 EwasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
|
||||
return clz64(arg[0] & uint32_t(-1)) - 32;
|
||||
else if (_fun == "i64.clz"_yulstring)
|
||||
return clz64(arg[0]);
|
||||
else if (_fun == "i32.ctz"_yulstring)
|
||||
return ctz32(uint32_t(arg[0] & uint32_t(-1)));
|
||||
else if (_fun == "i64.ctz"_yulstring)
|
||||
return ctz64(arg[0]);
|
||||
|
||||
string prefix = _fun.str();
|
||||
string suffix;
|
||||
@ -207,6 +255,8 @@ u256 EwasmBuiltinInterpreter::evalWasmBuiltin(string const& _fun, vector<Word> c
|
||||
return arg[0] != arg[1] ? 1 : 0;
|
||||
else if (_fun == "eqz")
|
||||
return arg[0] == 0 ? 1 : 0;
|
||||
else if (_fun == "popcnt")
|
||||
return popcnt(arg[0]);
|
||||
else if (_fun == "lt_u")
|
||||
return arg[0] < arg[1] ? 1 : 0;
|
||||
else if (_fun == "gt_u")
|
||||
|
Loading…
Reference in New Issue
Block a user