| // 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); |