blob: b595cc1205336be5a39bef052e56edb4fef9d99b [file] [log] [blame]
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// This is a small "shim" program which is used when wasm32 unit tests are run
// in this repository. This program is intended to be run in node.js and will
// load a wasm module into memory, instantiate it with a set of imports, and
// then run it.
//
// There's a bunch of helper functions defined here in `imports.env`, but note
// that most of them aren't actually needed to execute most programs. Many of
// these are just intended for completeness or debugging. Hopefully over time
// nothing here is needed for completeness.
const fs = require('fs');
const process = require('process');
const buffer = fs.readFileSync(process.argv[2]);
Error.stackTraceLimit = 20;
let m = new WebAssembly.Module(buffer);
let memory = null;
function copystr(a, b) {
if (memory === null) {
return null
}
let view = new Uint8Array(memory.buffer).slice(a, a + b);
return String.fromCharCode.apply(null, view);
}
let imports = {};
imports.env = {
// These are generated by LLVM itself for various intrinsic calls. Hopefully
// one day this is not necessary and something will automatically do this.
fmod: function(x, y) { return x % y; },
exp2: function(x) { return Math.pow(2, x); },
exp2f: function(x) { return Math.pow(2, x); },
ldexp: function(x, y) { return x * Math.pow(2, y); },
ldexpf: function(x, y) { return x * Math.pow(2, y); },
log10: function(x) { return Math.log10(x); },
log10f: function(x) { return Math.log10(x); },
// These are called in src/libstd/sys/wasm/stdio.rs and are used when
// debugging is enabled.
rust_wasm_write_stdout: function(a, b) {
let s = copystr(a, b);
if (s !== null) {
process.stdout.write(s);
}
},
rust_wasm_write_stderr: function(a, b) {
let s = copystr(a, b);
if (s !== null) {
process.stderr.write(s);
}
},
// These are called in src/libstd/sys/wasm/args.rs and are used when
// debugging is enabled.
rust_wasm_args_count: function() {
if (memory === null)
return 0;
return process.argv.length - 2;
},
rust_wasm_args_arg_size: function(i) {
return process.argv[i + 2].length;
},
rust_wasm_args_arg_fill: function(idx, ptr) {
let arg = process.argv[idx + 2];
let view = new Uint8Array(memory.buffer);
for (var i = 0; i < arg.length; i++) {
view[ptr + i] = arg.charCodeAt(i);
}
},
// These are called in src/libstd/sys/wasm/os.rs and are used when
// debugging is enabled.
rust_wasm_getenv_len: function(a, b) {
let key = copystr(a, b);
if (key === null) {
return -1;
}
if (!(key in process.env)) {
return -1;
}
return process.env[key].length;
},
rust_wasm_getenv_data: function(a, b, ptr) {
let key = copystr(a, b);
let value = process.env[key];
let view = new Uint8Array(memory.buffer);
for (var i = 0; i < value.length; i++) {
view[ptr + i] = value.charCodeAt(i);
}
},
};
let module_imports = WebAssembly.Module.imports(m);
for (var i = 0; i < module_imports.length; i++) {
let imp = module_imports[i];
if (imp.module != 'env') {
continue
}
if (imp.name == 'memory' && imp.kind == 'memory') {
memory = new WebAssembly.Memory({initial: 20});
imports.env.memory = memory;
}
}
let instance = new WebAssembly.Instance(m, imports);