Skip to content

Instantly share code, notes, and snippets.

@ColinEberhardt
Last active January 16, 2018 22:04
Show Gist options
  • Select an option

  • Save ColinEberhardt/9695e6369864a309661e016863a227f1 to your computer and use it in GitHub Desktop.

Select an option

Save ColinEberhardt/9695e6369864a309661e016863a227f1 to your computer and use it in GitHub Desktop.
WebAssembly integer operations
license: mit
<!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 :-(
});
asm ``echodiv_sdiv_u
 m  n 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment