Merge pull request #8046 from imapp-pl/ewasm-interpreter-improvements

Wasm dialect extension and  EWasm interpreter improvements.
This commit is contained in:
Alex Beregszaszi 2019-12-18 22:04:34 +00:00 committed by GitHub
commit 37ae229a4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 1 deletions

View File

@ -56,10 +56,16 @@ WasmDialect::WasmDialect():
addFunction("i64.eqz", 1, 1);
m_functions["i64.eqz"_yulstring].returns.front() = "i32"_yulstring;
addFunction("i64.clz", 1, 1);
addFunction("i64.store", 2, 0, false);
m_functions["i64.store"_yulstring].parameters.front() = "i32"_yulstring;
m_functions["i64.store"_yulstring].sideEffects.invalidatesStorage = false;
addFunction("i64.store8", 2, 0, false);
m_functions["i64.store8"_yulstring].parameters.front() = "i32"_yulstring;
m_functions["i64.store8"_yulstring].sideEffects.invalidatesStorage = false;
addFunction("i64.load", 1, 1, false);
m_functions["i64.load"_yulstring].parameters.front() = "i32"_yulstring;
m_functions["i64.load"_yulstring].sideEffects.invalidatesStorage = false;

View File

@ -49,6 +49,21 @@ void copyZeroExtended(
_target[_targetOffset + i] = _sourceOffset + i < _source.size() ? _source[_sourceOffset + i] : 0;
}
/// Count leading zeros for uint64
uint64_t clz(uint64_t _v)
{
if (_v == 0)
return 64;
uint64_t r = 0;
while (!(_v & 0x8000000000000000))
{
r += 1;
_v = _v << 1;
}
return r;
}
}
using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
@ -119,6 +134,8 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
return arg[0] != arg[1] ? 1 : 0;
else if (_fun == "i64.eqz"_yulstring)
return arg[0] == 0 ? 1 : 0;
else if (_fun == "i64.clz"_yulstring)
return clz(arg[0]);
else if (_fun == "i64.lt_u"_yulstring)
return arg[0] < arg[1] ? 1 : 0;
else if (_fun == "i64.gt_u"_yulstring)
@ -133,6 +150,12 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
writeMemoryWord(arg[0], arg[1]);
return 0;
}
else if (_fun == "i64.store8"_yulstring)
{
accessMemory(arg[0], 1);
writeMemoryByte(arg[0], static_cast<uint8_t>(arg[1] & 0xff));
return 0;
}
else if (_fun == "i64.load"_yulstring)
{
accessMemory(arg[0], 8);
@ -148,7 +171,7 @@ u256 EWasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector<u256> const& _a
// TODO this does not read the address, but is consistent with
// EVM interpreter implementation.
// If we take the address into account, this needs to use readAddress.
writeU128(arg[0], m_state.balance);
writeU128(arg[1], m_state.balance);
return 0;
}
else if (_fun == "eth.getBlockHash"_yulstring)
@ -368,6 +391,11 @@ void EWasmBuiltinInterpreter::writeMemoryWord(uint64_t _offset, uint64_t _value)
m_state.memory[_offset + i] = uint8_t((_value >> (i * 8)) & 0xff);
}
void EWasmBuiltinInterpreter::writeMemoryByte(uint64_t _offset, uint8_t _value)
{
m_state.memory[_offset] = _value;
}
void EWasmBuiltinInterpreter::writeU256(uint64_t _offset, u256 _value, size_t _croppedTo)
{
accessMemory(_offset, _croppedTo);

View File

@ -86,6 +86,9 @@ private:
/// Writes a word to memory (little-endian)
/// Does not adjust msize, use @a accessMemory for that
void writeMemoryWord(uint64_t _offset, uint64_t _value);
/// Writes a byte to memory
/// Does not adjust msize, use @a accessMemory for that
void writeMemoryByte(uint64_t _offset, uint8_t _value);
/// Helper for eth.* builtins. Writes to memory (big-endian) and always returns zero.
void writeU256(uint64_t _offset, dev::u256 _value, size_t _croppedTo = 32);