Built with blockbuilder.org
forked from anonymous's block: WebAssembly integer operations
| license: mit |
Built with blockbuilder.org
forked from anonymous's block: WebAssembly integer operations
| <!DOCTYPE html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script src="script.js"></script> | |
| </head> | |
| <body> | |
| </body> |
| // test.wasm is the following: | |
| // (module | |
| // (func $div_s (param i32) (param i32) (result i32) | |
| // (get_local 0) | |
| // (get_local 1) | |
| // (i32.div_s) | |
| // ) | |
| // (func $div_u (param i32) (param i32) (result i32) | |
| // (get_local 0) | |
| // (get_local 1) | |
| // (i32.div_u) | |
| // ) | |
| // (func $echo (param i32) (result i32) | |
| // (get_local 0) | |
| // ) | |
| // (export "echo" (func $echo)) | |
| // (export "div_s" (func $div_s)) | |
| // (export "div_u" (func $div_u)) | |
| // ) | |
| fetch('test.wasm').then(response => | |
| response.arrayBuffer() | |
| ).then(bytes => | |
| WebAssembly.instantiate(bytes) | |
| ).then(module => { | |
| const {div_s, div_u, echo} = module.instance.exports; | |
| // As per the wasm spec, the ToWebAssemblyValue algoritm coerces a JS value | |
| // into a wasm value | |
| // https://webassembly.github.io/spec/js-api/index.html#exported-function-exotic-objects | |
| // for i32, this is the ToInt32 as described here: | |
| // https://tc39.github.io/ecma262/#sec-toint32 | |
| const positiveMod = (a, n) => { | |
| const remain = a % n; | |
| return remain > 0 ? remain : remain + n; | |
| }; | |
| const toWebAssemblyValue = value => { | |
| const sign = value > 0 ? 1 : -1; | |
| const ints = sign * Math.floor(Math.abs(value)); | |
| const int32bit = positiveMod(ints, Math.pow(2, 32)); | |
| return int32bit >= Math.pow(2, 31) ? int32bit - Math.pow(2, 32) : int32bit; | |
| }; | |
| // The inverse algorithm, ToJSValue, is slighty more vaguelly described | |
| // as " the Number value for i32" | |
| // my guess is that this is the following conversion | |
| const toJSValue = value => value | 0; | |
| // testing the conversion to wasm and back to JS, via a simple echo function | |
| // that simply returns the input argument | |
| const value = 335991768761; | |
| console.log("echo wasm", m.exports.echo(value)); | |
| console.log("echo js", toJSValue(toWebAssemblyValue(value))); | |
| // this works just fine! | |
| // unsigned division - here's a problem case (found through random number testing) | |
| const a = 335991768761; | |
| const b = 77022195821; | |
| console.log("div_u wasm", m.exports.div_u(a, b)); | |
| console.log("div_u js", | |
| toJSValue(div_u(toWebAssemblyValue(a), toWebAssemblyValue(b))) | |
| ); | |
| // these give a different result :-( | |
| }); |