porffor 0.0.0-05f898f → 0.0.0-151f80e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/compiler/2c.js +353 -349
- package/compiler/codeGen.js +398 -101
- package/compiler/embedding.js +9 -5
- package/compiler/index.js +3 -3
- package/compiler/opt.js +14 -18
- package/compiler/prototype.js +168 -29
- package/compiler/sections.js +19 -4
- package/out.exe +0 -0
- package/package.json +1 -1
- package/r.js +39 -1
- package/rhemyn/compile.js +1 -1
- package/runner/index.js +5 -3
- package/runner/info.js +37 -2
- package/tmp.c +26 -23
package/compiler/embedding.js
CHANGED
@@ -9,11 +9,15 @@ export const number = (n, valtype = valtypeBinary) => {
|
|
9
9
|
}
|
10
10
|
};
|
11
11
|
|
12
|
-
const
|
12
|
+
export const enforceOneByte = arr => [ arr[0] ?? 0 ];
|
13
|
+
export const enforceTwoBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0 ];
|
14
|
+
export const enforceFourBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0, arr[3] ?? 0 ];
|
15
|
+
export const enforceEightBytes = arr => [ arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0, arr[3] ?? 0, arr[4] ?? 0, arr[5] ?? 0, arr[6] ?? 0, arr[7] ?? 0 ];
|
16
|
+
|
13
17
|
export const i32x4 = (a, b, c, d) => [ [
|
14
18
|
...Opcodes.v128_const,
|
15
|
-
...
|
16
|
-
...
|
17
|
-
...
|
18
|
-
...
|
19
|
+
...enforceFourBytes(signedLEB128(a)),
|
20
|
+
...enforceFourBytes(signedLEB128(b)),
|
21
|
+
...enforceFourBytes(signedLEB128(c)),
|
22
|
+
...enforceFourBytes(signedLEB128(d))
|
19
23
|
] ];
|
package/compiler/index.js
CHANGED
@@ -59,7 +59,7 @@ export default (code, flags) => {
|
|
59
59
|
if (flags.includes('info')) console.log(`1. parsed in ${(performance.now() - t0).toFixed(2)}ms`);
|
60
60
|
|
61
61
|
const t1 = performance.now();
|
62
|
-
const { funcs, globals, tags, exceptions, pages } = codeGen(program);
|
62
|
+
const { funcs, globals, tags, exceptions, pages, data } = codeGen(program);
|
63
63
|
if (flags.includes('info')) console.log(`2. generated code in ${(performance.now() - t1).toFixed(2)}ms`);
|
64
64
|
|
65
65
|
if (process.argv.includes('-funcs')) logFuncs(funcs, globals, exceptions);
|
@@ -71,14 +71,14 @@ export default (code, flags) => {
|
|
71
71
|
if (process.argv.includes('-opt-funcs')) logFuncs(funcs, globals, exceptions);
|
72
72
|
|
73
73
|
const t3 = performance.now();
|
74
|
-
const sections = produceSections(funcs, globals, tags, pages, flags);
|
74
|
+
const sections = produceSections(funcs, globals, tags, pages, data, flags);
|
75
75
|
if (flags.includes('info')) console.log(`4. produced sections in ${(performance.now() - t3).toFixed(2)}ms`);
|
76
76
|
|
77
77
|
if (allocLog) {
|
78
78
|
const wasmPages = Math.ceil((pages.size * pageSize) / 65536);
|
79
79
|
const bytes = wasmPages * 65536;
|
80
80
|
log('alloc', `\x1B[1mallocated ${bytes / 1024}KiB\x1B[0m for ${pages.size} things using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}`);
|
81
|
-
|
81
|
+
console.log([...pages.keys()].map(x => `\x1B[36m - ${x}\x1B[0m`).join('\n') + '\n');
|
82
82
|
}
|
83
83
|
|
84
84
|
const out = { wasm: sections, funcs, globals, tags, exceptions, pages };
|
package/compiler/opt.js
CHANGED
@@ -317,28 +317,24 @@ export default (funcs, globals) => {
|
|
317
317
|
continue;
|
318
318
|
}
|
319
319
|
|
320
|
-
|
321
|
-
const
|
320
|
+
// remove unneeded before get with update exprs (n++, etc) when value is unused
|
321
|
+
if (i < wasm.length - 4 && lastInst[1] === inst[1] && lastInst[0] === Opcodes.local_get && inst[0] === Opcodes.local_get && wasm[i + 1][0] === Opcodes.const && [Opcodes.add, Opcodes.sub].includes(wasm[i + 2][0]) && wasm[i + 3][0] === Opcodes.local_set && wasm[i + 3][1] === inst[1] && (wasm[i + 4][0] === Opcodes.drop || wasm[i + 4][0] === Opcodes.br)) {
|
322
|
+
// local.get 1
|
323
|
+
// local.get 1
|
324
|
+
// -->
|
325
|
+
// local.get 1
|
322
326
|
|
323
|
-
|
324
|
-
|
325
|
-
if (lastLastInst[0] === Opcodes.end && lastInst[1] === inst[1] && lastInst[0] === Opcodes.local_get && inst[0] === Opcodes.local_get) {
|
326
|
-
// local.get 1
|
327
|
-
// local.get 1
|
328
|
-
// -->
|
329
|
-
// local.get 1
|
330
|
-
|
331
|
-
// remove drop at the end as well
|
332
|
-
if (wasm[i + 4][0] === Opcodes.drop) {
|
333
|
-
wasm.splice(i + 4, 1);
|
334
|
-
}
|
327
|
+
// remove drop at the end as well
|
328
|
+
if (wasm[i + 4][0] === Opcodes.drop) wasm.splice(i + 4, 1);
|
335
329
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
}
|
330
|
+
wasm.splice(i, 1); // remove this inst (second get)
|
331
|
+
i--;
|
332
|
+
continue;
|
340
333
|
}
|
341
334
|
|
335
|
+
if (i < 2) continue;
|
336
|
+
const lastLastInst = wasm[i - 2];
|
337
|
+
|
342
338
|
if (lastLastInst[1] === inst[1] && inst[0] === Opcodes.local_get && lastInst[0] === Opcodes.local_tee && lastLastInst[0] === Opcodes.local_set) {
|
343
339
|
// local.set x
|
344
340
|
// local.tee y
|
package/compiler/prototype.js
CHANGED
@@ -23,6 +23,9 @@ const TYPES = {
|
|
23
23
|
|
24
24
|
export const PrototypeFuncs = function() {
|
25
25
|
const noUnlikelyChecks = process.argv.includes('-funsafe-no-unlikely-proto-checks');
|
26
|
+
let zeroChecks = process.argv.find(x => x.startsWith('-funsafe-zero-proto-checks='));
|
27
|
+
if (zeroChecks) zeroChecks = zeroChecks.split('=')[1].split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
|
28
|
+
else zeroChecks = {};
|
26
29
|
|
27
30
|
this[TYPES._array] = {
|
28
31
|
// lX = local accessor of X ({ get, set }), iX = local index of X, wX = wasm ops of X
|
@@ -36,7 +39,7 @@ export const PrototypeFuncs = function() {
|
|
36
39
|
[ Opcodes.i32_lt_s ],
|
37
40
|
[ Opcodes.if, Blocktype.void ],
|
38
41
|
[ Opcodes.local_get, iTmp ],
|
39
|
-
...length.
|
42
|
+
...length.getCachedI32(),
|
40
43
|
[ Opcodes.i32_add ],
|
41
44
|
[ Opcodes.local_set, iTmp ],
|
42
45
|
[ Opcodes.end ],
|
@@ -47,7 +50,7 @@ export const PrototypeFuncs = function() {
|
|
47
50
|
[ Opcodes.i32_lt_s ],
|
48
51
|
|
49
52
|
[ Opcodes.local_get, iTmp ],
|
50
|
-
...length.
|
53
|
+
...length.getCachedI32(),
|
51
54
|
[ Opcodes.i32_ge_s ],
|
52
55
|
[ Opcodes.i32_or ],
|
53
56
|
|
@@ -67,7 +70,7 @@ export const PrototypeFuncs = function() {
|
|
67
70
|
// todo: only for 1 argument
|
68
71
|
push: (pointer, length, wNewMember) => [
|
69
72
|
// get memory offset of array at last index (length)
|
70
|
-
...length.
|
73
|
+
...length.getCachedI32(),
|
71
74
|
...number(ValtypeSize[valtype], Valtype.i32),
|
72
75
|
[ Opcodes.i32_mul ],
|
73
76
|
|
@@ -79,17 +82,17 @@ export const PrototypeFuncs = function() {
|
|
79
82
|
|
80
83
|
// bump array length by 1 and return it
|
81
84
|
...length.setI32([
|
82
|
-
...length.
|
85
|
+
...length.getCachedI32(),
|
83
86
|
...number(1, Valtype.i32),
|
84
87
|
[ Opcodes.i32_add ]
|
85
88
|
]),
|
86
89
|
|
87
|
-
...length.get
|
90
|
+
...length.get()
|
88
91
|
],
|
89
92
|
|
90
93
|
pop: (pointer, length) => [
|
91
94
|
// if length == 0, noop
|
92
|
-
...length.
|
95
|
+
...length.getCachedI32(),
|
93
96
|
[ Opcodes.i32_eqz ],
|
94
97
|
[ Opcodes.if, Blocktype.void ],
|
95
98
|
...number(UNDEFINED),
|
@@ -100,13 +103,13 @@ export const PrototypeFuncs = function() {
|
|
100
103
|
|
101
104
|
// decrement length by 1
|
102
105
|
...length.setI32([
|
103
|
-
...length.
|
106
|
+
...length.getCachedI32(),
|
104
107
|
...number(1, Valtype.i32),
|
105
108
|
[ Opcodes.i32_sub ]
|
106
109
|
]),
|
107
110
|
|
108
111
|
// load last element
|
109
|
-
...length.
|
112
|
+
...length.getCachedI32(),
|
110
113
|
...number(ValtypeSize[valtype], Valtype.i32),
|
111
114
|
[ Opcodes.i32_mul ],
|
112
115
|
|
@@ -115,7 +118,7 @@ export const PrototypeFuncs = function() {
|
|
115
118
|
|
116
119
|
shift: (pointer, length) => [
|
117
120
|
// if length == 0, noop
|
118
|
-
...length.
|
121
|
+
...length.getCachedI32(),
|
119
122
|
Opcodes.i32_eqz,
|
120
123
|
[ Opcodes.if, Blocktype.void ],
|
121
124
|
...number(UNDEFINED),
|
@@ -126,7 +129,7 @@ export const PrototypeFuncs = function() {
|
|
126
129
|
|
127
130
|
// decrement length by 1
|
128
131
|
...length.setI32([
|
129
|
-
...length.
|
132
|
+
...length.getCachedI32(),
|
130
133
|
...number(1, Valtype.i32),
|
131
134
|
[ Opcodes.i32_sub ]
|
132
135
|
]),
|
@@ -140,14 +143,69 @@ export const PrototypeFuncs = function() {
|
|
140
143
|
...number(pointer + ValtypeSize.i32 + ValtypeSize[valtype], Valtype.i32), // src = base array index + length size + an index
|
141
144
|
...number(pageSize - ValtypeSize.i32 - ValtypeSize[valtype], Valtype.i32), // size = PageSize - length size - an index
|
142
145
|
[ ...Opcodes.memory_copy, 0x00, 0x00 ]
|
146
|
+
],
|
147
|
+
|
148
|
+
fill: (pointer, length, wElement, iTmp) => [
|
149
|
+
...wElement,
|
150
|
+
[ Opcodes.local_set, iTmp ],
|
151
|
+
|
152
|
+
// use cached length i32 as pointer
|
153
|
+
...length.getCachedI32(),
|
154
|
+
|
155
|
+
// length - 1 for indexes
|
156
|
+
...number(1, Valtype.i32),
|
157
|
+
[ Opcodes.i32_sub ],
|
158
|
+
|
159
|
+
// * sizeof value
|
160
|
+
...number(ValtypeSize[valtype], Valtype.i32),
|
161
|
+
[ Opcodes.i32_mul ],
|
162
|
+
|
163
|
+
...length.setCachedI32(),
|
164
|
+
|
165
|
+
...(noUnlikelyChecks ? [] : [
|
166
|
+
...length.getCachedI32(),
|
167
|
+
...number(0, Valtype.i32),
|
168
|
+
[ Opcodes.i32_lt_s ],
|
169
|
+
[ Opcodes.if, Blocktype.void ],
|
170
|
+
...number(pointer),
|
171
|
+
[ Opcodes.br, 1 ],
|
172
|
+
[ Opcodes.end ]
|
173
|
+
]),
|
174
|
+
|
175
|
+
[ Opcodes.loop, Blocktype.void ],
|
176
|
+
|
177
|
+
// set element using pointer
|
178
|
+
...length.getCachedI32(),
|
179
|
+
[ Opcodes.local_get, iTmp ],
|
180
|
+
[ Opcodes.store, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
|
181
|
+
|
182
|
+
// pointer - sizeof value
|
183
|
+
...length.getCachedI32(),
|
184
|
+
...number(ValtypeSize[valtype], Valtype.i32),
|
185
|
+
[ Opcodes.i32_sub ],
|
186
|
+
|
187
|
+
...length.setCachedI32(),
|
188
|
+
|
189
|
+
// if pointer >= 0, loop
|
190
|
+
...length.getCachedI32(),
|
191
|
+
...number(0, Valtype.i32),
|
192
|
+
[ Opcodes.i32_ge_s ],
|
193
|
+
[ Opcodes.br_if, 0 ],
|
194
|
+
|
195
|
+
[ Opcodes.end ],
|
196
|
+
|
197
|
+
// return this array
|
198
|
+
...number(pointer)
|
143
199
|
]
|
144
200
|
};
|
145
201
|
|
146
202
|
this[TYPES._array].at.local = Valtype.i32;
|
147
203
|
this[TYPES._array].push.noArgRetLength = true;
|
204
|
+
this[TYPES._array].fill.local = valtypeBinary;
|
205
|
+
this[TYPES._array].fill.returnType = TYPES._array;
|
148
206
|
|
149
207
|
this[TYPES.string] = {
|
150
|
-
at: (pointer, length, wIndex, iTmp, arrayShell) => {
|
208
|
+
at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
|
151
209
|
const [ newOut, newPointer ] = arrayShell(1, 'i16');
|
152
210
|
|
153
211
|
return [
|
@@ -166,7 +224,7 @@ export const PrototypeFuncs = function() {
|
|
166
224
|
[ Opcodes.i32_lt_s ],
|
167
225
|
[ Opcodes.if, Blocktype.void ],
|
168
226
|
[ Opcodes.local_get, iTmp ],
|
169
|
-
...length.
|
227
|
+
...length.getCachedI32(),
|
170
228
|
[ Opcodes.i32_add ],
|
171
229
|
[ Opcodes.local_set, iTmp ],
|
172
230
|
[ Opcodes.end ],
|
@@ -177,7 +235,7 @@ export const PrototypeFuncs = function() {
|
|
177
235
|
[ Opcodes.i32_lt_s ],
|
178
236
|
|
179
237
|
[ Opcodes.local_get, iTmp ],
|
180
|
-
...length.
|
238
|
+
...length.getCachedI32(),
|
181
239
|
[ Opcodes.i32_ge_s ],
|
182
240
|
[ Opcodes.i32_or ],
|
183
241
|
|
@@ -202,7 +260,7 @@ export const PrototypeFuncs = function() {
|
|
202
260
|
},
|
203
261
|
|
204
262
|
// todo: out of bounds properly
|
205
|
-
charAt: (pointer, length, wIndex,
|
263
|
+
charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
|
206
264
|
const [ newOut, newPointer ] = arrayShell(1, 'i16');
|
207
265
|
|
208
266
|
return [
|
@@ -233,39 +291,120 @@ export const PrototypeFuncs = function() {
|
|
233
291
|
return [
|
234
292
|
...wIndex,
|
235
293
|
Opcodes.i32_to,
|
236
|
-
[ Opcodes.local_set, iTmp ],
|
237
294
|
|
238
|
-
|
239
|
-
|
295
|
+
...(zeroChecks.charcodeat ? [] : [
|
296
|
+
[ Opcodes.local_set, iTmp ],
|
297
|
+
|
298
|
+
// index < 0
|
299
|
+
...(noUnlikelyChecks ? [] : [
|
300
|
+
[ Opcodes.local_get, iTmp ],
|
301
|
+
...number(0, Valtype.i32),
|
302
|
+
[ Opcodes.i32_lt_s ],
|
303
|
+
]),
|
304
|
+
|
305
|
+
// index >= length
|
306
|
+
[ Opcodes.local_get, iTmp ],
|
307
|
+
...length.getCachedI32(),
|
308
|
+
[ Opcodes.i32_ge_s ],
|
309
|
+
|
310
|
+
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
311
|
+
[ Opcodes.if, Blocktype.void ],
|
312
|
+
...number(NaN),
|
313
|
+
[ Opcodes.br, 1 ],
|
314
|
+
[ Opcodes.end ],
|
315
|
+
|
240
316
|
[ Opcodes.local_get, iTmp ],
|
241
|
-
...number(0, Valtype.i32),
|
242
|
-
[ Opcodes.i32_lt_s ],
|
243
317
|
]),
|
244
318
|
|
245
|
-
|
319
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
320
|
+
[ Opcodes.i32_mul ],
|
321
|
+
|
322
|
+
// load current string ind {arg}
|
323
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
|
324
|
+
Opcodes.i32_from_u
|
325
|
+
];
|
326
|
+
},
|
327
|
+
|
328
|
+
isWellFormed: (pointer, length, wIndex, iTmp, iTmp2, arrayShell, { wellFormed } = {}) => {
|
329
|
+
// aot approx metadata
|
330
|
+
if (wellFormed != null) return number(wellFormed ? 1 : 0);
|
331
|
+
|
332
|
+
return [
|
333
|
+
// note: we cannot presume it begins as 0 in case it was used previously
|
334
|
+
...number(0, Valtype.i32),
|
335
|
+
[ Opcodes.local_set, iTmp ],
|
336
|
+
|
337
|
+
[ Opcodes.loop, Blocktype.void ],
|
338
|
+
|
339
|
+
[ Opcodes.block, Blocktype.void ],
|
340
|
+
|
246
341
|
[ Opcodes.local_get, iTmp ],
|
247
|
-
...
|
342
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32) ],
|
343
|
+
[ Opcodes.local_set, iTmp2 ],
|
344
|
+
|
345
|
+
// if not surrogate, continue
|
346
|
+
[ Opcodes.local_get, iTmp2 ],
|
347
|
+
...number(0xF800, Valtype.i32),
|
348
|
+
[ Opcodes.i32_and ],
|
349
|
+
...number(0xD800, Valtype.i32),
|
350
|
+
[ Opcodes.i32_ne ],
|
351
|
+
[ Opcodes.br_if, 0 ],
|
352
|
+
|
353
|
+
// if not leading surrogate, return false
|
354
|
+
[ Opcodes.local_get, iTmp2 ],
|
355
|
+
...number(0xDC00, Valtype.i32),
|
248
356
|
[ Opcodes.i32_ge_s ],
|
357
|
+
[ Opcodes.if, Blocktype.void ],
|
358
|
+
...number(0),
|
359
|
+
[ Opcodes.br, 3 ],
|
360
|
+
[ Opcodes.end ],
|
249
361
|
|
250
|
-
|
362
|
+
// if not followed by trailing surrogate, return false
|
363
|
+
[ Opcodes.local_get, iTmp ],
|
364
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32 + ValtypeSize.i16) ],
|
365
|
+
...number(0xFC00, Valtype.i32),
|
366
|
+
[ Opcodes.i32_and ],
|
367
|
+
...number(0xDC00, Valtype.i32),
|
368
|
+
[ Opcodes.i32_ne ],
|
251
369
|
[ Opcodes.if, Blocktype.void ],
|
252
|
-
...number(
|
253
|
-
[ Opcodes.br,
|
370
|
+
...number(0),
|
371
|
+
[ Opcodes.br, 3 ],
|
254
372
|
[ Opcodes.end ],
|
255
373
|
|
374
|
+
// bump index again since gone through two valid chars
|
256
375
|
[ Opcodes.local_get, iTmp ],
|
257
376
|
...number(ValtypeSize.i16, Valtype.i32),
|
377
|
+
[ Opcodes.i32_add ],
|
378
|
+
[ Opcodes.local_set, iTmp ],
|
379
|
+
|
380
|
+
[ Opcodes.end ],
|
381
|
+
|
382
|
+
// bump pointer and loop if not at the end
|
383
|
+
[ Opcodes.local_get, iTmp ],
|
384
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
385
|
+
[ Opcodes.i32_add ],
|
386
|
+
[ Opcodes.local_tee, iTmp ],
|
387
|
+
|
388
|
+
...length.getCachedI32(),
|
389
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
258
390
|
[ Opcodes.i32_mul ],
|
391
|
+
[ Opcodes.i32_ne ],
|
392
|
+
[ Opcodes.br_if, 0 ],
|
259
393
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
394
|
+
[ Opcodes.end ],
|
395
|
+
|
396
|
+
// return true
|
397
|
+
...number(1)
|
398
|
+
]
|
399
|
+
}
|
265
400
|
};
|
266
401
|
|
267
402
|
this[TYPES.string].at.local = Valtype.i32;
|
268
403
|
this[TYPES.string].at.returnType = TYPES.string;
|
269
404
|
this[TYPES.string].charAt.returnType = TYPES.string;
|
270
405
|
this[TYPES.string].charCodeAt.local = Valtype.i32;
|
406
|
+
|
407
|
+
this[TYPES.string].isWellFormed.local = Valtype.i32;
|
408
|
+
this[TYPES.string].isWellFormed.local2 = Valtype.i32;
|
409
|
+
this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
|
271
410
|
};
|
package/compiler/sections.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Valtype, FuncType, Empty, ExportDesc, Section, Magic, ModuleVersion, Opcodes, PageSize } from './wasmSpec.js';
|
2
|
-
import { encodeVector, encodeString, encodeLocal } from './encoding.js';
|
2
|
+
import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128 } from './encoding.js';
|
3
3
|
import { number } from './embedding.js';
|
4
4
|
import { importedFuncs } from './builtins.js';
|
5
5
|
|
@@ -20,7 +20,7 @@ const chHint = (topTier, baselineTier, strategy) => {
|
|
20
20
|
return (strategy | (baselineTier << 2) | (topTier << 4));
|
21
21
|
};
|
22
22
|
|
23
|
-
export default (funcs, globals, tags, pages, flags) => {
|
23
|
+
export default (funcs, globals, tags, pages, data, flags) => {
|
24
24
|
const types = [], typeCache = {};
|
25
25
|
|
26
26
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
@@ -105,6 +105,8 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
105
105
|
|
106
106
|
const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, x.index ]);
|
107
107
|
|
108
|
+
if (process.argv.includes('-always-memory') && pages.size === 0) pages.set('-always-memory', 0);
|
109
|
+
|
108
110
|
const usesMemory = pages.size > 0;
|
109
111
|
const memorySection = !usesMemory ? [] : createSection(
|
110
112
|
Section.memory,
|
@@ -155,13 +157,24 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
155
157
|
encodeVector(types)
|
156
158
|
);
|
157
159
|
|
160
|
+
const dataSection = data.length === 0 ? [] : createSection(
|
161
|
+
Section.data,
|
162
|
+
encodeVector(data.map(x => [ 0x00, Opcodes.i32_const, ...signedLEB128(x.offset), Opcodes.end, ...encodeVector(x.bytes) ]))
|
163
|
+
);
|
164
|
+
|
165
|
+
const dataCountSection = data.length === 0 ? [] : createSection(
|
166
|
+
Section.data_count,
|
167
|
+
unsignedLEB128(data.length)
|
168
|
+
);
|
169
|
+
|
158
170
|
if (process.argv.includes('-sections')) console.log({
|
159
171
|
typeSection: typeSection.map(x => x.toString(16)),
|
160
172
|
importSection: importSection.map(x => x.toString(16)),
|
161
173
|
funcSection: funcSection.map(x => x.toString(16)),
|
162
174
|
globalSection: globalSection.map(x => x.toString(16)),
|
163
175
|
exportSection: exportSection.map(x => x.toString(16)),
|
164
|
-
codeSection: codeSection.map(x => x.toString(16))
|
176
|
+
codeSection: codeSection.map(x => x.toString(16)),
|
177
|
+
dataSection: dataSection.map(x => x.toString(16)),
|
165
178
|
});
|
166
179
|
|
167
180
|
return Uint8Array.from([
|
@@ -175,6 +188,8 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
175
188
|
...tagSection,
|
176
189
|
...globalSection,
|
177
190
|
...exportSection,
|
178
|
-
...
|
191
|
+
...dataCountSection,
|
192
|
+
...codeSection,
|
193
|
+
...dataSection
|
179
194
|
]);
|
180
195
|
};
|
package/out.exe
CHANGED
Binary file
|
package/package.json
CHANGED
package/r.js
CHANGED
@@ -1 +1,39 @@
|
|
1
|
-
|
1
|
+
compareArray.isSameValue = function(a, b) {
|
2
|
+
if (a === 0 && b === 0) return 1 / a === 1 / b;
|
3
|
+
if (a !== a && b !== b) return true;
|
4
|
+
|
5
|
+
return a === b;
|
6
|
+
};
|
7
|
+
|
8
|
+
function compareArray(a, b) {
|
9
|
+
// if either are nullish
|
10
|
+
if (a == null || b == null) return false;
|
11
|
+
|
12
|
+
// megahack: all arrays from now on will be >0 pointer
|
13
|
+
const _hack = '';
|
14
|
+
|
15
|
+
// hack: enforce type inference of being arrays
|
16
|
+
a ??= [];
|
17
|
+
b ??= [];
|
18
|
+
|
19
|
+
if (b.length !== a.length) {
|
20
|
+
return false;
|
21
|
+
}
|
22
|
+
|
23
|
+
for (var i = 0; i < a.length; i++) {
|
24
|
+
if (!compareArray.isSameValue(b[i], a[i])) {
|
25
|
+
return false;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
return true;
|
30
|
+
}
|
31
|
+
|
32
|
+
console.log(compareArray(null, []));
|
33
|
+
console.log(compareArray(undefined, []));
|
34
|
+
|
35
|
+
console.log(compareArray([], []));
|
36
|
+
console.log(compareArray([ 1 ], []));
|
37
|
+
console.log(compareArray([ 1 ], [ 1 ]));
|
38
|
+
console.log(compareArray([ 1, 2 ], [ 1 ]));
|
39
|
+
console.log(compareArray([ 1, 2 ], [ 1, 2 ]));
|
package/rhemyn/compile.js
CHANGED
@@ -21,7 +21,7 @@ const generate = (node, negated = false, get = true, func = 'test') => {
|
|
21
21
|
out = [
|
22
22
|
// set length local
|
23
23
|
[ Opcodes.local_get, BasePointer ],
|
24
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
24
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
25
25
|
[ Opcodes.local_set, Length ],
|
26
26
|
|
27
27
|
// set iter pointer local as base + sizeof i32 initially
|
package/runner/index.js
CHANGED
@@ -34,12 +34,14 @@ const source = fs.readFileSync(file, 'utf8');
|
|
34
34
|
|
35
35
|
let cache = '';
|
36
36
|
const print = str => {
|
37
|
-
cache += str;
|
37
|
+
/* cache += str;
|
38
38
|
|
39
39
|
if (str === '\n') {
|
40
40
|
process.stdout.write(cache);
|
41
41
|
cache = '';
|
42
|
-
}
|
42
|
+
} */
|
43
|
+
|
44
|
+
process.stdout.write(str);
|
43
45
|
};
|
44
46
|
|
45
47
|
try {
|
@@ -49,5 +51,5 @@ try {
|
|
49
51
|
if (cache) process.stdout.write(cache);
|
50
52
|
} catch (e) {
|
51
53
|
if (cache) process.stdout.write(cache);
|
52
|
-
console.error(`${e.constructor.name}: ${e.message}`);
|
54
|
+
console.error(process.argv.includes('-i') ? e : `${e.constructor.name}: ${e.message}`);
|
53
55
|
}
|
package/runner/info.js
CHANGED
@@ -36,7 +36,7 @@ const print = str => {
|
|
36
36
|
};
|
37
37
|
|
38
38
|
const t0 = performance.now();
|
39
|
-
const { wasm, exports } = await compile(source, raw ? [ 'module' ] : [ 'module', 'info' ], {}, print);
|
39
|
+
const { wasm, exports, pages } = await compile(source, raw ? [ 'module' ] : [ 'module', 'info' ], {}, print);
|
40
40
|
|
41
41
|
if (!raw && typeof Deno === 'undefined') fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
42
42
|
|
@@ -51,4 +51,39 @@ if (!process.argv.includes('-no-run')) {
|
|
51
51
|
}
|
52
52
|
|
53
53
|
if (!raw) console.log(bold(`wasm binary is ${wasm.byteLength} bytes`));
|
54
|
-
if (!raw) console.log(`total: ${(performance.now() - t0).toFixed(2)}ms`);
|
54
|
+
if (!raw) console.log(`total: ${(performance.now() - t0).toFixed(2)}ms`);
|
55
|
+
|
56
|
+
if (!raw && process.argv.includes('-mem') && exports.$) {
|
57
|
+
console.log();
|
58
|
+
|
59
|
+
let lastMemory, lastPages;
|
60
|
+
const PageSize = 65536;
|
61
|
+
const memoryToString = mem => {
|
62
|
+
let out = '';
|
63
|
+
const pages = lastPages.length;
|
64
|
+
const wasmPages = mem.buffer.byteLength / PageSize;
|
65
|
+
|
66
|
+
out += `\x1B[1mallocated ${mem.buffer.byteLength / 1024}KiB\x1B[0m for ${pages} things using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}\n`;
|
67
|
+
|
68
|
+
const buf = new Uint8Array(mem.buffer);
|
69
|
+
|
70
|
+
for (let i = 0; i < pages; i++) {
|
71
|
+
out += `\x1B[36m${lastPages[i]}\x1B[2m | \x1B[0m`;
|
72
|
+
|
73
|
+
for (let j = 0; j < 50; j++) {
|
74
|
+
const val = buf[i * pageSize + j];
|
75
|
+
if (val === 0) out += '\x1B[2m';
|
76
|
+
out += val.toString(16).padStart(2, '0');
|
77
|
+
if (val === 0) out += '\x1B[0m';
|
78
|
+
out += ' ';
|
79
|
+
}
|
80
|
+
out += '\n';
|
81
|
+
}
|
82
|
+
|
83
|
+
return out;
|
84
|
+
};
|
85
|
+
|
86
|
+
lastPages = [...pages.keys()];
|
87
|
+
lastMemory = exports.$;
|
88
|
+
console.log(memoryToString(lastMemory));
|
89
|
+
}
|