@@ -28,14 +28,76 @@ let m = new WebAssembly.Module(buffer);
2828
2929let memory = null;
3030
31+ function viewstruct(data, fields) {
32+ return new Uint32Array(memory.buffer).subarray(data/4, data/4 + fields);
33+ }
34+
3135function copystr(a, b) {
32- if (memory === null) {
33- return null
34- }
35- let view = new Uint8Array(memory.buffer).slice(a, a + b);
36+ let view = new Uint8Array(memory.buffer).subarray(a, a + b);
3637 return String.fromCharCode.apply(null, view);
3738}
3839
40+ function syscall_write([fd, ptr, len]) {
41+ let s = copystr(ptr, len);
42+ switch (fd) {
43+ case 1: process.stdout.write(s); break;
44+ case 2: process.stderr.write(s); break;
45+ }
46+ }
47+
48+ function syscall_exit([code]) {
49+ process.exit(code);
50+ }
51+
52+ function syscall_args(params) {
53+ let [ptr, len] = params;
54+
55+ // Calculate total required buffer size
56+ let totalLen = -1;
57+ for (let i = 2; i < process.argv.length; ++i) {
58+ totalLen += Buffer.byteLength(process.argv[i]) + 1;
59+ }
60+ if (totalLen < 0) { totalLen = 0; }
61+ params[2] = totalLen;
62+
63+ // If buffer is large enough, copy data
64+ if (len >= totalLen) {
65+ let view = new Uint8Array(memory.buffer);
66+ for (let i = 2; i < process.argv.length; ++i) {
67+ let value = process.argv[i];
68+ Buffer.from(value).copy(view, ptr);
69+ ptr += Buffer.byteLength(process.argv[i]) + 1;
70+ }
71+ }
72+ }
73+
74+ function syscall_getenv(params) {
75+ let [keyPtr, keyLen, valuePtr, valueLen] = params;
76+
77+ let key = copystr(keyPtr, keyLen);
78+ let value = process.env[key];
79+
80+ if (value == null) {
81+ params[4] = 0xFFFFFFFF;
82+ } else {
83+ let view = new Uint8Array(memory.buffer);
84+ let totalLen = Buffer.byteLength(value);
85+ params[4] = totalLen;
86+ if (valueLen >= totalLen) {
87+ Buffer.from(value).copy(view, valuePtr);
88+ }
89+ }
90+ }
91+
92+ function syscall_time(params) {
93+ let t = Date.now();
94+ let secs = Math.floor(t / 1000);
95+ let millis = t % 1000;
96+ params[1] = Math.floor(secs / 0x100000000);
97+ params[2] = secs % 0x100000000;
98+ params[3] = Math.floor(millis * 1000000);
99+ }
100+
39101let imports = {};
40102imports.env = {
41103 // These are generated by LLVM itself for various intrinsic calls. Hopefully
@@ -48,68 +110,25 @@ imports.env = {
48110 log10: Math.log10,
49111 log10f: Math.log10,
50112
51- // These are called in src/libstd/sys/wasm/stdio.rs and are used when
52- // debugging is enabled.
53- rust_wasm_write_stdout: function(a, b) {
54- let s = copystr(a, b);
55- if (s !== null) {
56- process.stdout.write(s);
57- }
58- },
59- rust_wasm_write_stderr: function(a, b) {
60- let s = copystr(a, b);
61- if (s !== null) {
62- process.stderr.write(s);
63- }
64- },
65-
66- // These are called in src/libstd/sys/wasm/args.rs and are used when
67- // debugging is enabled.
68- rust_wasm_args_count: function() {
69- if (memory === null)
70- return 0;
71- return process.argv.length - 2;
72- },
73- rust_wasm_args_arg_size: function(i) {
74- return Buffer.byteLength(process.argv[i + 2]);
75- },
76- rust_wasm_args_arg_fill: function(idx, ptr) {
77- let arg = process.argv[idx + 2];
78- let view = new Uint8Array(memory.buffer);
79- Buffer.from(arg).copy(view, ptr);
80- },
81-
82- // These are called in src/libstd/sys/wasm/os.rs and are used when
83- // debugging is enabled.
84- rust_wasm_getenv_len: function(a, b) {
85- let key = copystr(a, b);
86- if (key === null) {
87- return -1;
113+ rust_wasm_syscall: function(index, data) {
114+ switch (index) {
115+ case 1: syscall_write(viewstruct(data, 3)); return true;
116+ case 2: syscall_exit(viewstruct(data, 1)); return true;
117+ case 3: syscall_args(viewstruct(data, 3)); return true;
118+ case 4: syscall_getenv(viewstruct(data, 5)); return true;
119+ case 6: syscall_time(viewstruct(data, 4)); return true;
120+ default:
121+ console.log("Unsupported syscall: " + index);
122+ return false;
88123 }
89- if (!(key in process.env)) {
90- return -1;
91- }
92- return Buffer.byteLength(process.env[key]);
93- },
94- rust_wasm_getenv_data: function(a, b, ptr) {
95- let key = copystr(a, b);
96- let value = process.env[key];
97- let view = new Uint8Array(memory.buffer);
98- Buffer.from(value).copy(view, ptr);
99- },
100- };
101-
102- let module_imports = WebAssembly.Module.imports(m);
103-
104- for (var i = 0; i < module_imports.length; i++) {
105- let imp = module_imports[i];
106- if (imp.module != 'env') {
107- continue
108124 }
109- if (imp.name == 'memory' && imp.kind == 'memory') {
110- memory = new WebAssembly.Memory({initial: 20});
111- imports.env.memory = memory;
112- }
113- }
125+ };
114126
115127let instance = new WebAssembly.Instance(m, imports);
128+ memory = instance.exports.memory;
129+ try {
130+ instance.exports.main();
131+ } catch (e) {
132+ console.error(e);
133+ process.exit(101);
134+ }
0 commit comments