Open jwasinger opened 6 years ago
Here is the wast segment that is generated for callcall_00
:
(module
(import "ethereum" "storageStore" (func $storageStore (param i32 i32) ))
(import "ethereum" "call" (func $call (param i64 i32 i32 i32 i32) (result i32)))
(import "ethereum" "useGas" (func $useGas (param i64)))
(global $cb_dest (mut i32) (i32.const 0))
(global $sp (mut i32) (i32.const -32))
(global $init (mut i32) (i32.const 0))
;; memory related global
(global $memstart i32 (i32.const 33832))
;; the number of 256 words stored in memory
(global $wordCount (mut i64) (i64.const 0))
;; what was charged for the last memory allocation
(global $prevMemCost (mut i64) (i64.const 0))
;; TODO: memory should only be 1, but can't resize right now
(memory 500)
(export "memory" (memory 0))
;; generated by ./wasm/generateInterface.js
(func $SSTORE (call $storageStore(get_global $sp)(i32.add (get_global $sp) (i32.const -32))))(func $PUSH
(param $a0 i64)
(param $a1 i64)
(param $a2 i64)
(param $a3 i64)
(local $sp i32)
;; increament stack pointer
(set_local $sp (i32.add (get_global $sp) (i32.const 32)))
(i64.store (get_local $sp) (get_local $a3))
(i64.store (i32.add (get_local $sp) (i32.const 8)) (get_local $a2))
(i64.store (i32.add (get_local $sp) (i32.const 16)) (get_local $a1))
(i64.store (i32.add (get_local $sp) (i32.const 24)) (get_local $a0))
)
;; generated by ./wasm/generateInterface.js
(func $CALL (local $offset0 i32)(local $length0 i32) (set_local $offset0
(call $check_overflow
(i64.load (i32.add (get_global $sp) (i32.const -96)))
(i64.load (i32.add (get_global $sp) (i32.const -88)))
(i64.load (i32.add (get_global $sp) (i32.const -80)))
(i64.load (i32.add (get_global $sp) (i32.const -72)))))(set_local $length0
(call $check_overflow
(i64.load (i32.add (get_global $sp) (i32.const -128)))
(i64.load (i32.add (get_global $sp) (i32.const -120)))
(i64.load (i32.add (get_global $sp) (i32.const -112)))
(i64.load (i32.add (get_global $sp) (i32.const -104)))))
(call $memusegas (get_local $offset0) (get_local $length0))
(set_local $offset0 (i32.add (get_global $memstart) (get_local $offset0))) (i64.store
(i32.add (get_global $sp) (i32.const -192))
(i64.extend_u/i32
(i32.eqz (call $call(call $check_overflow_i64
(i64.load (i32.add (get_global $sp) (i32.const 0)))
(i64.load (i32.add (get_global $sp) (i32.const 8)))
(i64.load (i32.add (get_global $sp) (i32.const 16)))
(i64.load (i32.add (get_global $sp) (i32.const 24))))
(i32.add (get_global $sp) (i32.const -32))(i32.add (get_global $sp) (i32.const -64))(get_local $offset0)(get_local $length0)
;; zero out mem
(i64.store (i32.add (get_global $sp) (i32.const -128)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const -136)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const -144)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const -152)) (i64.const 0))
;; zero out mem
(i64.store (i32.add (get_global $sp) (i32.const -160)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const -168)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const -176)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const -184)) (i64.const 0))) ;; flip CALL result from EEI to EVM convention (0 -> 1, 1,2,.. -> 1)
)))
;; zero out mem
(i64.store (i32.add (get_global $sp) (i32.const -168)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const -176)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const -184)) (i64.const 0)))(func $bswap_i64
(param $int i64)
(result i64)
(i64.or
(i64.or
(i64.or
(i64.and (i64.shr_u (get_local $int) (i64.const 56)) (i64.const 0xff)) ;; 7 -> 0
(i64.and (i64.shr_u (get_local $int) (i64.const 40)) (i64.const 0xff00))) ;; 6 -> 1
(i64.or
(i64.and (i64.shr_u (get_local $int) (i64.const 24)) (i64.const 0xff0000)) ;; 5 -> 2
(i64.and (i64.shr_u (get_local $int) (i64.const 8)) (i64.const 0xff000000)))) ;; 4 -> 3
(i64.or
(i64.or
(i64.and (i64.shl (get_local $int) (i64.const 8)) (i64.const 0xff00000000)) ;; 3 -> 4
(i64.and (i64.shl (get_local $int) (i64.const 24)) (i64.const 0xff0000000000))) ;; 2 -> 5
(i64.or
(i64.and (i64.shl (get_local $int) (i64.const 40)) (i64.const 0xff000000000000)) ;; 1 -> 6
(i64.and (i64.shl (get_local $int) (i64.const 56)) (i64.const 0xff00000000000000))))) ;; 0 -> 7
)
(func $bswap_m256
(param $sp i32)
(result i32)
(local $temp i64)
(set_local $temp (call $bswap_i64 (i64.load (get_local $sp))))
(i64.store (get_local $sp) (call $bswap_i64 (i64.load (i32.add (get_local $sp) (i32.const 24)))))
(i64.store (i32.add (get_local $sp) (i32.const 24)) (get_local $temp))
(set_local $temp (call $bswap_i64 (i64.load (i32.add (get_local $sp) (i32.const 8)))))
(i64.store (i32.add (get_local $sp) (i32.const 8)) (call $bswap_i64 (i64.load (i32.add (get_local $sp) (i32.const 16)))))
(i64.store (i32.add (get_local $sp) (i32.const 16)) (get_local $temp))
(get_local $sp)
)
(func $callback
(call $main)
)
(func $callback_32
(param $result i32)
(i64.store (get_global $sp) (i64.extend_u/i32 (get_local $result)))
;; zero out mem
(i64.store (i32.add (get_global $sp) (i32.const 24)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const 16)) (i64.const 0))
(i64.store (i32.add (get_global $sp) (i32.const 8)) (i64.const 0))
(call $main)
)
(func $check_overflow
(param $a i64)
(param $b i64)
(param $c i64)
(param $d i64)
(result i32)
(local $MAX_INT i32)
(set_local $MAX_INT (i32.const -1))
(if
(i32.and
(i32.and
(i64.eqz (get_local $d))
(i64.eqz (get_local $c)))
(i32.and
(i64.eqz (get_local $b))
(i64.lt_u (get_local $a) (i64.extend_u/i32 (get_local $MAX_INT)))))
(return (i32.wrap/i64 (get_local $a))))
(return (get_local $MAX_INT))
)
(func $check_overflow_i64
(param $a i64)
(param $b i64)
(param $c i64)
(param $d i64)
(result i64)
(if
(i32.and
(i32.and
(i64.eqz (get_local $d))
(i64.eqz (get_local $c)))
(i64.eqz (get_local $b)))
(return (get_local $a)))
(return (i64.const 0xffffffffffffffff))
)
;;
;; memcpy from ewasm-libc/ewasm-cleanup
;;
(func $memset
(param $ptr i32)
(param $value i32)
(param $length i32)
(result i32)
(local $i i32)
(set_local $i (i32.const 0))
(block $done
(loop $loop
(if (i32.ge_u (get_local $i) (get_local $length))
(br $done)
)
(i32.store8 (i32.add (get_local $ptr) (get_local $i)) (get_local $value))
(set_local $i (i32.add (get_local $i) (i32.const 1)))
(br $loop)
)
)
(get_local $ptr)
)
(func $memusegas
(param $offset i32)
(param $length i32)
(local $cost i64)
;; the number of new words being allocated
(local $newWordCount i64)
(if (i32.eqz (get_local $length))
(then (return))
)
;; const newMemoryWordCount = Math.ceil[[offset + length] / 32]
(set_local $newWordCount
(i64.div_u (i64.add (i64.const 31) (i64.add (i64.extend_u/i32 (get_local $offset)) (i64.extend_u/i32 (get_local $length))))
(i64.const 32)))
;;if [runState.highestMem >= highestMem] return
(if (i64.le_u (get_local $newWordCount) (get_global $wordCount))
(then (return))
)
;; words * 3 + words ^2 / 512
(set_local $cost
(i64.add
(i64.mul (get_local $newWordCount) (i64.const 3))
(i64.div_u
(i64.mul (get_local $newWordCount)
(get_local $newWordCount))
(i64.const 512))))
(call $useGas (i64.sub (get_local $cost) (get_global $prevMemCost)))
(set_global $prevMemCost (get_local $cost))
(set_global $wordCount (get_local $newWordCount))
;; grow actual memory
;; the first 31704 bytes are guaranteed to be available
;; adjust for 32 bytes - the maximal size of MSTORE write
;; TODO it should be current_memory * page_size
(set_local $offset (i32.add (get_local $length) (i32.add (get_local $offset) (get_global $memstart))))
(if (i32.gt_u (get_local $offset) (i32.mul (i32.const 65536) (current_memory)))
(then
(drop (grow_memory
(i32.div_u (i32.add (i32.const 65535) (i32.sub (get_local $offset) (current_memory))) (i32.const 65536))))
)
)
)
(func $main (export "main") (local $jump_dest i32) (local $jump_map_switch i32) (set_local $jump_dest (i32.const -1)) (block $done (loop $loop (block $0
(if
(i32.eqz (get_global $init))
(then
(set_global $init (i32.const 1))
(br $0))
(else
;; the callback dest can never be in the first block
(if (i32.eq (get_global $cb_dest) (i32.const 0))
(then
(unreachable)
)
(else
;; return callback destination and zero out $cb_dest
(set_local $jump_map_switch (get_global $cb_dest))
(set_global $cb_dest (i32.const 0))
(br_table $0 (get_local $jump_map_switch))
)))))(call $useGas (i64.const 24))(if (i32.gt_s (get_global $sp) (i32.const 32480))
(then (unreachable)))(call $PUSH (i64.const 0)(i64.const 0)(i64.const 0)(i64.const 64))(set_global $sp(i32.add(get_global $sp)(i32.const 32)))
(call $PUSH (i64.const 0)(i64.const 0)(i64.const 0)(i64.const 0))(set_global $sp(i32.add(get_global $sp)(i32.const 32)))
(call $PUSH (i64.const 0)(i64.const 0)(i64.const 0)(i64.const 64))(set_global $sp(i32.add(get_global $sp)(i32.const 32)))
(call $PUSH (i64.const 0)(i64.const 0)(i64.const 0)(i64.const 0))(set_global $sp(i32.add(get_global $sp)(i32.const 32)))
(call $PUSH (i64.const 0)(i64.const 0)(i64.const 0)(i64.const 1))(set_global $sp(i32.add(get_global $sp)(i32.const 32)))
(call $PUSH (i64.const 0)(i64.const 268435456)(i64.const 0)(i64.const 1))(set_global $sp(i32.add(get_global $sp)(i32.const 32)))
(call $PUSH (i64.const 0)(i64.const 0)(i64.const 0)(i64.const 350000))(set_global $sp(i32.add(get_global $sp)(i32.const 32)))
(call $CALL)
(set_global $sp(i32.add(get_global $sp)(i32.const -192)))
(call $PUSH (i64.const 0)(i64.const 0)(i64.const 0)(i64.const 0))(set_global $sp(i32.add(get_global $sp)(i32.const 32)))
(call $SSTORE)
(set_global $sp(i32.add(get_global $sp)(i32.const -64)))
)))
)
Here is the fix for this specific issue: https://github.com/ewasm/evm2wasm/pull/276
Linting generated wast using Binaryen would be nice to have for CircleCI.
Currently, the wast for
CALL
( https://github.com/ewasm/evm2wasm/blob/master/wasm/wast.json#L91 ) fails to load. We should add linting to CircleCI to catch changes that break Binaryen.