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)
|
### 0.6.12 (unreleased)
|
||||||
|
|
||||||
|
Language Features:
|
||||||
|
* Wasm backend: Add ``i32.ctz``, ``i64.ctz``, ``i32.popcnt``, and ``i64.popcnt``.
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
* Code Generator: Evaluate ``keccak256`` of string literals at compile-time.
|
* Code Generator: Evaluate ``keccak256`` of string literals at compile-time.
|
||||||
|
|
||||||
|
@ -38,13 +38,18 @@ WasmDialect::WasmDialect()
|
|||||||
"add",
|
"add",
|
||||||
"sub",
|
"sub",
|
||||||
"mul",
|
"mul",
|
||||||
|
// TODO: div_s
|
||||||
"div_u",
|
"div_u",
|
||||||
|
// TODO: rem_s
|
||||||
"rem_u",
|
"rem_u",
|
||||||
"and",
|
"and",
|
||||||
"or",
|
"or",
|
||||||
"xor",
|
"xor",
|
||||||
"shl",
|
"shl",
|
||||||
|
// TODO: shr_s
|
||||||
"shr_u",
|
"shr_u",
|
||||||
|
// TODO: rotl
|
||||||
|
// TODO: rotr
|
||||||
})
|
})
|
||||||
addFunction(t.str() + "." + name, {t, t}, {t});
|
addFunction(t.str() + "." + name, {t, t}, {t});
|
||||||
|
|
||||||
@ -52,9 +57,13 @@ WasmDialect::WasmDialect()
|
|||||||
for (auto const& name: {
|
for (auto const& name: {
|
||||||
"eq",
|
"eq",
|
||||||
"ne",
|
"ne",
|
||||||
|
// TODO: lt_s
|
||||||
"lt_u",
|
"lt_u",
|
||||||
|
// TODO: gt_s
|
||||||
"gt_u",
|
"gt_u",
|
||||||
|
// TODO: le_s
|
||||||
"le_u",
|
"le_u",
|
||||||
|
// TODO: ge_s
|
||||||
"ge_u"
|
"ge_u"
|
||||||
})
|
})
|
||||||
addFunction(t.str() + "." + name, {t, t}, {i32});
|
addFunction(t.str() + "." + name, {t, t}, {i32});
|
||||||
@ -62,8 +71,13 @@ WasmDialect::WasmDialect()
|
|||||||
addFunction("i32.eqz", {i32}, {i32});
|
addFunction("i32.eqz", {i32}, {i32});
|
||||||
addFunction("i64.eqz", {i64}, {i32});
|
addFunction("i64.eqz", {i64}, {i32});
|
||||||
|
|
||||||
addFunction("i32.clz", {i32}, {i32});
|
for (auto t: types)
|
||||||
addFunction("i64.clz", {i64}, {i64});
|
for (auto const& name: {
|
||||||
|
"clz",
|
||||||
|
"ctz",
|
||||||
|
"popcnt",
|
||||||
|
})
|
||||||
|
addFunction(t.str() + "." + name, {t}, {t});
|
||||||
|
|
||||||
addFunction("i32.wrap_i64", {i64}, {i32});
|
addFunction("i32.wrap_i64", {i64}, {i32});
|
||||||
|
|
||||||
@ -73,6 +87,7 @@ WasmDialect::WasmDialect()
|
|||||||
m_functions["i32.store"_yulstring].sideEffects.invalidatesStorage = false;
|
m_functions["i32.store"_yulstring].sideEffects.invalidatesStorage = false;
|
||||||
addFunction("i64.store", {i32, i64}, {}, false);
|
addFunction("i64.store", {i32, i64}, {}, false);
|
||||||
m_functions["i64.store"_yulstring].sideEffects.invalidatesStorage = 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);
|
addFunction("i32.store8", {i32, i32}, {}, false);
|
||||||
m_functions["i32.store8"_yulstring].sideEffects.invalidatesStorage = 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.invalidatesMemory = false;
|
||||||
m_functions["i64.load"_yulstring].sideEffects.sideEffectFree = true;
|
m_functions["i64.load"_yulstring].sideEffects.sideEffectFree = true;
|
||||||
m_functions["i64.load"_yulstring].sideEffects.sideEffectFreeIfNoMSize = 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.
|
// Drop is actually overloaded for all types, but Yul does not support that.
|
||||||
// Because of that, we introduce "i32.drop" and "i64.drop".
|
// Because of that, we introduce "i32.drop" and "i64.drop".
|
||||||
|
@ -67,6 +67,50 @@ uint64_t clz64(uint64_t _v)
|
|||||||
return r;
|
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>>;
|
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;
|
return clz64(arg[0] & uint32_t(-1)) - 32;
|
||||||
else if (_fun == "i64.clz"_yulstring)
|
else if (_fun == "i64.clz"_yulstring)
|
||||||
return clz64(arg[0]);
|
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 prefix = _fun.str();
|
||||||
string suffix;
|
string suffix;
|
||||||
@ -207,6 +255,8 @@ u256 EwasmBuiltinInterpreter::evalWasmBuiltin(string const& _fun, vector<Word> c
|
|||||||
return arg[0] != arg[1] ? 1 : 0;
|
return arg[0] != arg[1] ? 1 : 0;
|
||||||
else if (_fun == "eqz")
|
else if (_fun == "eqz")
|
||||||
return arg[0] == 0 ? 1 : 0;
|
return arg[0] == 0 ? 1 : 0;
|
||||||
|
else if (_fun == "popcnt")
|
||||||
|
return popcnt(arg[0]);
|
||||||
else if (_fun == "lt_u")
|
else if (_fun == "lt_u")
|
||||||
return arg[0] < arg[1] ? 1 : 0;
|
return arg[0] < arg[1] ? 1 : 0;
|
||||||
else if (_fun == "gt_u")
|
else if (_fun == "gt_u")
|
||||||
|
Loading…
Reference in New Issue
Block a user