Implemented some (but not all) of the switch to async stack-pops.
See the comment on popInt in stack.nim.
This commit is contained in:
parent
62a1878270
commit
7d7480b325
|
@ -34,252 +34,274 @@ import
|
|||
const
|
||||
addOp: Vm2OpFn = proc (k: var Vm2Ctx) =
|
||||
## 0x01, Addition
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
lhs + rhs
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
lhs + rhs
|
||||
|
||||
mulOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x02, Multiplication
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
lhs * rhs
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
lhs * rhs
|
||||
|
||||
subOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x03, Substraction
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
lhs - rhs
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
lhs - rhs
|
||||
|
||||
divideOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x04, Division
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
if rhs == 0:
|
||||
# EVM special casing of div by 0
|
||||
zero(UInt256)
|
||||
else:
|
||||
lhs div rhs
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
if rhs == 0:
|
||||
# EVM special casing of div by 0
|
||||
zero(UInt256)
|
||||
else:
|
||||
lhs div rhs
|
||||
|
||||
|
||||
sdivOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x05, Signed division
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
|
||||
var r: UInt256
|
||||
if rhs != 0:
|
||||
var a = lhs
|
||||
var b = rhs
|
||||
var signA, signB: bool
|
||||
extractSign(a, signA)
|
||||
extractSign(b, signB)
|
||||
r = a div b
|
||||
setSign(r, signA xor signB)
|
||||
k.cpt.stack.push(r)
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
var r: UInt256
|
||||
if rhs != 0:
|
||||
var a = lhs
|
||||
var b = rhs
|
||||
var signA, signB: bool
|
||||
extractSign(a, signA)
|
||||
extractSign(b, signB)
|
||||
r = a div b
|
||||
setSign(r, signA xor signB)
|
||||
cpt.stack.push(r)
|
||||
|
||||
|
||||
moduloOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x06, Modulo
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
if rhs == 0:
|
||||
zero(UInt256)
|
||||
else:
|
||||
lhs mod rhs
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
if rhs == 0:
|
||||
zero(UInt256)
|
||||
else:
|
||||
lhs mod rhs
|
||||
|
||||
|
||||
smodOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x07, Signed modulo
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
|
||||
var r: UInt256
|
||||
if rhs != 0:
|
||||
var sign: bool
|
||||
var v = lhs
|
||||
var m = rhs
|
||||
extractSign(m, sign)
|
||||
extractSign(v, sign)
|
||||
r = v mod m
|
||||
setSign(r, sign)
|
||||
k.cpt.stack.push(r)
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
var r: UInt256
|
||||
if rhs != 0:
|
||||
var sign: bool
|
||||
var v = lhs
|
||||
var m = rhs
|
||||
extractSign(m, sign)
|
||||
extractSign(v, sign)
|
||||
r = v mod m
|
||||
setSign(r, sign)
|
||||
cpt.stack.push(r)
|
||||
|
||||
|
||||
addmodOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x08, Modulo addition
|
||||
## Intermediate computations do not roll over at 2^256
|
||||
let (lhs, rhs, modulus) = k.cpt.stack.popInt(3)
|
||||
|
||||
k.cpt.stack.push:
|
||||
if modulus == 0:
|
||||
zero(UInt256)
|
||||
else:
|
||||
addmod(lhs, rhs, modulus)
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs, modulus: UInt256):
|
||||
cpt.stack.push:
|
||||
if modulus == 0:
|
||||
zero(UInt256)
|
||||
else:
|
||||
addmod(lhs, rhs, modulus)
|
||||
|
||||
|
||||
mulmodOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x09, Modulo multiplication
|
||||
## Intermediate computations do not roll over at 2^256
|
||||
let (lhs, rhs, modulus) = k.cpt.stack.popInt(3)
|
||||
|
||||
k.cpt.stack.push:
|
||||
if modulus == 0:
|
||||
zero(UInt256)
|
||||
else:
|
||||
mulmod(lhs, rhs, modulus)
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs, modulus: UInt256):
|
||||
cpt.stack.push:
|
||||
if modulus == 0:
|
||||
zero(UInt256)
|
||||
else:
|
||||
mulmod(lhs, rhs, modulus)
|
||||
|
||||
|
||||
expOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x0A, Exponentiation
|
||||
let (base, exponent) = k.cpt.stack.popInt(2)
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (base, exponent: UInt256):
|
||||
|
||||
k.cpt.gasMeter.consumeGas(
|
||||
k.cpt.gasCosts[Exp].d_handler(exponent),
|
||||
reason = "EXP: exponent bytes")
|
||||
cpt.gasMeter.consumeGas(
|
||||
cpt.gasCosts[Exp].d_handler(exponent),
|
||||
reason = "EXP: exponent bytes")
|
||||
|
||||
k.cpt.stack.push:
|
||||
if not base.isZero:
|
||||
base.pow(exponent)
|
||||
elif exponent.isZero:
|
||||
# https://github.com/ethereum/yellowpaper/issues/257
|
||||
# https://github.com/ethereum/tests/pull/460
|
||||
# https://github.com/ewasm/evm2wasm/issues/137
|
||||
1.u256
|
||||
else:
|
||||
zero(UInt256)
|
||||
cpt.stack.push:
|
||||
if not base.isZero:
|
||||
base.pow(exponent)
|
||||
elif exponent.isZero:
|
||||
# https://github.com/ethereum/yellowpaper/issues/257
|
||||
# https://github.com/ethereum/tests/pull/460
|
||||
# https://github.com/ewasm/evm2wasm/issues/137
|
||||
1.u256
|
||||
else:
|
||||
zero(UInt256)
|
||||
|
||||
|
||||
signExtendOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x0B, Sign extend
|
||||
## Extend length of two’s complement signed integer.
|
||||
let (bits, value) = k.cpt.stack.popInt(2)
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (bits, value: UInt256):
|
||||
|
||||
var res: UInt256
|
||||
if bits <= 31.u256:
|
||||
let
|
||||
one = 1.u256
|
||||
testBit = bits.truncate(int) * 8 + 7
|
||||
bitPos = one shl testBit
|
||||
mask = bitPos - one
|
||||
if not isZero(value and bitPos):
|
||||
res = value or (not mask)
|
||||
var res: UInt256
|
||||
if bits <= 31.u256:
|
||||
let
|
||||
one = 1.u256
|
||||
testBit = bits.truncate(int) * 8 + 7
|
||||
bitPos = one shl testBit
|
||||
mask = bitPos - one
|
||||
if not isZero(value and bitPos):
|
||||
res = value or (not mask)
|
||||
else:
|
||||
res = value and mask
|
||||
else:
|
||||
res = value and mask
|
||||
else:
|
||||
res = value
|
||||
k.cpt.stack.push:
|
||||
res
|
||||
res = value
|
||||
cpt.stack.push:
|
||||
res
|
||||
|
||||
|
||||
ltOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x10, Less-than comparison
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
(lhs < rhs).uint.u256
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
(lhs < rhs).uint.u256
|
||||
|
||||
gtOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x11, Greater-than comparison
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
(lhs > rhs).uint.u256
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
(lhs > rhs).uint.u256
|
||||
|
||||
sltOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x12, Signed less-than comparison
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
(cast[Int256](lhs) < cast[Int256](rhs)).uint.u256
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
(cast[Int256](lhs) < cast[Int256](rhs)).uint.u256
|
||||
|
||||
sgtOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x14, Signed greater-than comparison
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
(cast[Int256](lhs) > cast[Int256](rhs)).uint.u256
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
(cast[Int256](lhs) > cast[Int256](rhs)).uint.u256
|
||||
|
||||
eqOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x14, Signed greater-than comparison
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
(lhs == rhs).uint.u256
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
(lhs == rhs).uint.u256
|
||||
|
||||
isZeroOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x15, Check if zero
|
||||
let (value) = k.cpt.stack.popInt(1)
|
||||
k.cpt.stack.push:
|
||||
value.isZero.uint.u256
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValue do (value: UInt256):
|
||||
cpt.stack.push:
|
||||
value.isZero.uint.u256
|
||||
|
||||
andOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x16, Bitwise AND
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
lhs and rhs
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
lhs and rhs
|
||||
|
||||
orOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x17, Bitwise OR
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
lhs or rhs
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
lhs or rhs
|
||||
|
||||
xorOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x18, Bitwise XOR
|
||||
let (lhs, rhs) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
lhs xor rhs
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (lhs, rhs: UInt256):
|
||||
cpt.stack.push:
|
||||
lhs xor rhs
|
||||
|
||||
notOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x19, Check if zero
|
||||
let (value) = k.cpt.stack.popInt(1)
|
||||
k.cpt.stack.push:
|
||||
value.not
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValue do (value: UInt256):
|
||||
cpt.stack.push:
|
||||
value.not
|
||||
|
||||
byteOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
## 0x20, Retrieve single byte from word.
|
||||
let (position, value) = k.cpt.stack.popInt(2)
|
||||
k.cpt.stack.push:
|
||||
if position >= 32.u256:
|
||||
zero(UInt256)
|
||||
else:
|
||||
let pos = position.truncate(int)
|
||||
when system.cpuEndian == bigEndian:
|
||||
cast[array[32, byte]](value)[pos].u256
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (position, value: UInt256):
|
||||
cpt.stack.push:
|
||||
if position >= 32.u256:
|
||||
zero(UInt256)
|
||||
else:
|
||||
cast[array[32, byte]](value)[31 - pos].u256
|
||||
let pos = position.truncate(int)
|
||||
when system.cpuEndian == bigEndian:
|
||||
cast[array[32, byte]](value)[pos].u256
|
||||
else:
|
||||
cast[array[32, byte]](value)[31 - pos].u256
|
||||
|
||||
# Constantinople's new opcodes
|
||||
|
||||
shlOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
let (shift, num) = k.cpt.stack.popInt(2)
|
||||
let shiftLen = shift.safeInt
|
||||
if shiftLen >= 256:
|
||||
k.cpt.stack.push:
|
||||
0
|
||||
else:
|
||||
k.cpt.stack.push:
|
||||
num shl shiftLen
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (shift, num: UInt256):
|
||||
let shiftLen = shift.safeInt
|
||||
if shiftLen >= 256:
|
||||
cpt.stack.push:
|
||||
0
|
||||
else:
|
||||
cpt.stack.push:
|
||||
num shl shiftLen
|
||||
|
||||
shrOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
let (shift, num) = k.cpt.stack.popInt(2)
|
||||
let shiftLen = shift.safeInt
|
||||
if shiftLen >= 256:
|
||||
k.cpt.stack.push:
|
||||
0
|
||||
else:
|
||||
# uint version of `shr`
|
||||
k.cpt.stack.push:
|
||||
num shr shiftLen
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (shift, num: UInt256):
|
||||
let shiftLen = shift.safeInt
|
||||
if shiftLen >= 256:
|
||||
cpt.stack.push:
|
||||
0
|
||||
else:
|
||||
# uint version of `shr`
|
||||
cpt.stack.push:
|
||||
num shr shiftLen
|
||||
|
||||
sarOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
||||
let shiftLen = k.cpt.stack.popInt().safeInt
|
||||
let num = cast[Int256](k.cpt.stack.popInt())
|
||||
if shiftLen >= 256:
|
||||
if num.isNegative:
|
||||
k.cpt.stack.push:
|
||||
cast[UInt256]((-1).i256)
|
||||
let cpt = k.cpt
|
||||
cpt.popStackValues do (shift, numUncasted: UInt256):
|
||||
let shiftLen = shift.safeInt
|
||||
let num = cast[Int256](numUncasted)
|
||||
if shiftLen >= 256:
|
||||
if num.isNegative:
|
||||
cpt.stack.push:
|
||||
cast[UInt256]((-1).i256)
|
||||
else:
|
||||
cpt.stack.push:
|
||||
0
|
||||
else:
|
||||
k.cpt.stack. push:
|
||||
0
|
||||
else:
|
||||
# int version of `shr` then force the result
|
||||
# into uint256
|
||||
k.cpt.stack.push:
|
||||
cast[UInt256](num shr shiftLen)
|
||||
# int version of `shr` then force the result
|
||||
# into uint256
|
||||
cpt.stack.push:
|
||||
cast[UInt256](num shr shiftLen)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public, op exec table entries
|
||||
|
|
|
@ -194,6 +194,11 @@ proc replaceTopElement*(stack: Stack, newTopElem: StackElement) {.inline.} =
|
|||
# FIXME-Adam: These need to be removed, because calling waitFor is obviously
|
||||
# not what we want. I'm only leaving them here for now to keep the compiler
|
||||
# happy until we switch over to the new way.
|
||||
#
|
||||
# See oph_arithmetic.nim for examples of what to do instead. (Basically
|
||||
# call cpt.popStackValues.) I haven't finished propagating that change
|
||||
# through the rest of the code base. (At least not in this branch. I
|
||||
# did it once, but then the bits rotted.)
|
||||
proc popInt*(stack: var Stack): UInt256 =
|
||||
let elem = stack.popElement
|
||||
waitFor(elem.futureInt())
|
||||
|
|
Loading…
Reference in New Issue