Skip to content

Instantly share code, notes, and snippets.

@kripken
Last active June 13, 2019 22:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kripken/49fd1689d4c486f1f6c2a9e035164155 to your computer and use it in GitHub Desktop.
Save kripken/49fd1689d4c486f1f6c2a9e035164155 to your computer and use it in GitHub Desktop.
Factorial function in wasm instrumented as coroutine, printed 3 ways
;; printed in binaryen, to .wat s-expressions
(func $factorial-recursive (; 10 ;) (type $4) (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
(if
(i32.eq
(global.get $global$1)
(i32.const 2)
)
(block
(i32.store
(global.get $global$2)
(i32.add
(i32.load
(global.get $global$2)
)
(i32.const -12)
)
)
(local.set $0
(i32.load
(local.tee $2
(i32.load
(global.get $global$2)
)
)
)
)
(local.set $3
(i32.load offset=4
(local.get $2)
)
)
(local.set $2
(i32.load offset=8
(local.get $2)
)
)
)
)
(local.set $1
(block $label$2 (result i32)
(if
(i32.eq
(global.get $global$1)
(i32.const 2)
)
(block
(i32.store
(global.get $global$2)
(i32.add
(i32.load
(global.get $global$2)
)
(i32.const -4)
)
)
(local.set $1
(i32.load
(i32.load
(global.get $global$2)
)
)
)
)
)
(if
(i32.eqz
(global.get $global$1)
)
(if
(i32.eq
(local.get $0)
(i32.const 1)
)
(return
(i32.const 1)
)
)
)
(if
(select
(i32.eqz
(local.get $1)
)
(i32.const 1)
(global.get $global$1)
)
(block
(call $sleep)
(drop
(br_if $label$2
(i32.const 0)
(i32.eq
(global.get $global$1)
(i32.const 1)
)
)
)
)
)
(local.set $3
(select
(local.get $3)
(i32.sub
(local.get $0)
(i32.const 1)
)
(global.get $global$1)
)
)
(if
(select
(i32.eq
(local.get $1)
(i32.const 1)
)
(i32.const 1)
(global.get $global$1)
)
(block
(local.set $2
(call $factorial-recursive
(local.get $3)
)
)
(drop
(br_if $label$2
(i32.const 1)
(i32.eq
(global.get $global$1)
(i32.const 1)
)
)
)
)
)
(if
(i32.eqz
(global.get $global$1)
)
(return
(i32.mul
(local.get $0)
(local.get $2)
)
)
)
(unreachable)
)
)
(i32.store
(i32.load
(global.get $global$2)
)
(local.get $1)
)
(i32.store
(global.get $global$2)
(i32.add
(i32.load
(global.get $global$2)
)
(i32.const 4)
)
)
(i32.store
(local.tee $1
(i32.load
(global.get $global$2)
)
)
(local.get $0)
)
(i32.store offset=4
(local.get $1)
(local.get $3)
)
(i32.store offset=8
(local.get $1)
(local.get $2)
)
(i32.store
(global.get $global$2)
(i32.add
(i32.load
(global.get $global$2)
)
(i32.const 12)
)
)
(i32.const 0)
)
;; printed in wabt, to .wat stack format
(func $factorial-recursive (type 4) (param i32) (result i32)
(local i32 i32 i32)
global.get 1
i32.const 2
i32.eq
if ;; label = @1
global.get 2
global.get 2
i32.load
i32.const -12
i32.add
i32.store
global.get 2
i32.load
local.tee 2
i32.load
local.set 0
local.get 2
i32.load offset=4
local.set 3
local.get 2
i32.load offset=8
local.set 2
end
block (result i32) ;; label = @1
global.get 1
i32.const 2
i32.eq
if ;; label = @2
global.get 2
global.get 2
i32.load
i32.const -4
i32.add
i32.store
global.get 2
i32.load
i32.load
local.set 1
end
global.get 1
i32.eqz
if ;; label = @2
local.get 0
i32.const 1
i32.eq
if ;; label = @3
i32.const 1
return
end
end
local.get 1
i32.eqz
i32.const 1
global.get 1
select
if ;; label = @2
call $sleep
i32.const 0
global.get 1
i32.const 1
i32.eq
br_if 1 (;@1;)
drop
end
local.get 3
local.get 0
i32.const 1
i32.sub
global.get 1
select
local.set 3
local.get 1
i32.const 1
i32.eq
i32.const 1
global.get 1
select
if ;; label = @2
local.get 3
call $factorial-recursive
local.set 2
i32.const 1
global.get 1
i32.const 1
i32.eq
br_if 1 (;@1;)
drop
end
global.get 1
i32.eqz
if ;; label = @2
local.get 0
local.get 2
i32.mul
return
end
unreachable
end
local.set 1
global.get 2
i32.load
local.get 1
i32.store
global.get 2
global.get 2
i32.load
i32.const 4
i32.add
i32.store
global.get 2
i32.load
local.tee 1
local.get 0
i32.store
local.get 1
local.get 3
i32.store offset=4
local.get 1
local.get 2
i32.store offset=8
global.get 2
global.get 2
i32.load
i32.const 12
i32.add
i32.store
i32.const 0)
// printed in wasm2js
function factorial_recursive($0_1) {
$0_1 = $0_1 | 0;
var $1_1 = 0, $2_1 = 0, $3_1 = 0, $4_1 = 0;
if ((global$1 | 0) == 2) {
HEAP32[global$2 >> 2] = HEAP32[global$2 >> 2] + -12;
$1_1 = HEAP32[global$2 >> 2];
$0_1 = HEAP32[$1_1 >> 2];
$3_1 = HEAP32[$1_1 + 4 >> 2];
$1_1 = HEAP32[$1_1 + 8 >> 2];
}
if ((global$1 | 0) == 2) {
HEAP32[global$2 >> 2] = HEAP32[global$2 >> 2] + -4;
$2_1 = HEAP32[HEAP32[global$2 >> 2] >> 2];
}
if (!global$1) {
if (($0_1 | 0) == 1) {
return 1
}
}
label$2 : {
if (global$1 ? !$2_1 : 1) {
sleep();
if ((global$1 | 0) == 1) {
break label$2
}
}
$3_1 = global$1 ? $3_1 : $0_1 - 1 | 0;
if (global$1 ? ($2_1 | 0) == 1 : 1) {
$1_1 = factorial_recursive($3_1);
$4_1 = 1;
if ((global$1 | 0) == 1) {
break label$2
}
}
if (!global$1) {
return Math_imul($0_1, $1_1) | 0
}
abort();
}
HEAP32[HEAP32[global$2 >> 2] >> 2] = $4_1;
HEAP32[global$2 >> 2] = HEAP32[global$2 >> 2] + 4;
$2_1 = HEAP32[global$2 >> 2];
HEAP32[$2_1 >> 2] = $0_1;
HEAP32[$2_1 + 4 >> 2] = $3_1;
HEAP32[$2_1 + 8 >> 2] = $1_1;
HEAP32[global$2 >> 2] = HEAP32[global$2 >> 2] + 12;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment