porffor 0.16.0-a7bc359af → 0.16.0-a8928b26c
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 +5 -17
- package/compiler/2c.js +75 -15
- package/compiler/allocators.js +128 -0
- package/compiler/assemble.js +7 -1
- package/compiler/builtins/array.ts +3 -4
- package/compiler/builtins/date.ts +2 -5
- package/compiler/builtins/set.ts +2 -5
- package/compiler/codegen.js +248 -292
- package/compiler/generated_builtins.js +46 -46
- package/compiler/index.js +15 -1
- package/compiler/opt.js +7 -5
- package/compiler/parse.js +0 -6
- package/compiler/pgo.js +5 -0
- package/compiler/precompile.js +9 -6
- package/compiler/prefs.js +2 -3
- package/compiler/prototype.js +34 -43
- package/compiler/wasmSpec.js +2 -2
- package/compiler/wrap.js +2 -1
- package/package.json +1 -1
- package/runner/index.js +5 -0
- package/no_pgo.txt +0 -923
- package/pgo.txt +0 -916
package/compiler/codegen.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { Blocktype, Opcodes, Valtype,
|
2
|
-
import { ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from './encoding.js';
|
1
|
+
import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
|
2
|
+
import { ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector, read_signedLEB128 } from './encoding.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
4
|
import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
|
5
5
|
import { PrototypeFuncs } from './prototype.js';
|
@@ -9,15 +9,16 @@ import * as Rhemyn from '../rhemyn/compile.js';
|
|
9
9
|
import parse from './parse.js';
|
10
10
|
import { log } from './log.js';
|
11
11
|
import Prefs from './prefs.js';
|
12
|
+
import makeAllocator from './allocators.js';
|
12
13
|
|
13
14
|
let globals = {};
|
14
|
-
let globalInd = 0;
|
15
15
|
let tags = [];
|
16
16
|
let funcs = [];
|
17
17
|
let exceptions = [];
|
18
18
|
let funcIndex = {};
|
19
19
|
let currentFuncIndex = importedFuncs.length;
|
20
20
|
let builtinFuncs = {}, builtinVars = {}, prototypeFuncs = {};
|
21
|
+
let allocator;
|
21
22
|
|
22
23
|
class TodoError extends Error {
|
23
24
|
constructor(message) {
|
@@ -32,11 +33,6 @@ const todo = (scope, msg, expectsValue = undefined) => {
|
|
32
33
|
|
33
34
|
case 'runtime':
|
34
35
|
return internalThrow(scope, 'TodoError', msg, expectsValue);
|
35
|
-
|
36
|
-
// return [
|
37
|
-
// ...debug(`todo! ${msg}`),
|
38
|
-
// [ Opcodes.unreachable ]
|
39
|
-
// ];
|
40
36
|
}
|
41
37
|
};
|
42
38
|
|
@@ -181,12 +177,6 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
181
177
|
continue;
|
182
178
|
}
|
183
179
|
|
184
|
-
if (asm[0] === 'memory') {
|
185
|
-
allocPage(scope, 'asm instrinsic');
|
186
|
-
// todo: add to store/load offset insts
|
187
|
-
continue;
|
188
|
-
}
|
189
|
-
|
190
180
|
let inst = Opcodes[asm[0].replace('.', '_')];
|
191
181
|
if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
192
182
|
|
@@ -433,63 +423,12 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
433
423
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
434
424
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
435
425
|
|
436
|
-
if (assign && Prefs.aotPointerOpt) {
|
437
|
-
const pointer = scope.arrays?.get(name ?? '$undeclared');
|
438
|
-
|
439
|
-
return [
|
440
|
-
// setup right
|
441
|
-
...right,
|
442
|
-
Opcodes.i32_to_u,
|
443
|
-
[ Opcodes.local_set, rightPointer ],
|
444
|
-
|
445
|
-
// calculate length
|
446
|
-
...number(0, Valtype.i32), // base 0 for store later
|
447
|
-
|
448
|
-
...number(pointer, Valtype.i32),
|
449
|
-
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
450
|
-
[ Opcodes.local_tee, leftLength ],
|
451
|
-
|
452
|
-
[ Opcodes.local_get, rightPointer ],
|
453
|
-
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
454
|
-
[ Opcodes.local_tee, rightLength ],
|
455
|
-
|
456
|
-
[ Opcodes.i32_add ],
|
457
|
-
|
458
|
-
// store length
|
459
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(pointer) ],
|
460
|
-
|
461
|
-
// copy right
|
462
|
-
// dst = out pointer + length size + current length * sizeof valtype
|
463
|
-
...number(pointer + ValtypeSize.i32, Valtype.i32),
|
464
|
-
|
465
|
-
[ Opcodes.local_get, leftLength ],
|
466
|
-
...number(bytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
467
|
-
[ Opcodes.i32_mul ],
|
468
|
-
[ Opcodes.i32_add ],
|
469
|
-
|
470
|
-
// src = right pointer + length size
|
471
|
-
[ Opcodes.local_get, rightPointer ],
|
472
|
-
...number(ValtypeSize.i32, Valtype.i32),
|
473
|
-
[ Opcodes.i32_add ],
|
474
|
-
|
475
|
-
// size = right length * sizeof valtype
|
476
|
-
[ Opcodes.local_get, rightLength ],
|
477
|
-
...number(bytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
478
|
-
[ Opcodes.i32_mul ],
|
479
|
-
|
480
|
-
[ ...Opcodes.memory_copy, 0x00, 0x00 ],
|
481
|
-
|
482
|
-
// return new string (page)
|
483
|
-
...number(pointer)
|
484
|
-
];
|
485
|
-
}
|
486
|
-
|
487
426
|
const leftPointer = localTmp(scope, 'concat_left_pointer', Valtype.i32);
|
488
427
|
|
489
428
|
// alloc/assign array
|
490
|
-
const [ , pointer ] = makeArray(scope, {
|
429
|
+
const [ out, pointer ] = makeArray(scope, {
|
491
430
|
rawElements: new Array(0)
|
492
|
-
}, global, name, true, 'i16');
|
431
|
+
}, global, name, true, 'i16', true);
|
493
432
|
|
494
433
|
return [
|
495
434
|
// setup left
|
@@ -503,7 +442,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
503
442
|
[ Opcodes.local_set, rightPointer ],
|
504
443
|
|
505
444
|
// calculate length
|
506
|
-
...
|
445
|
+
...out,
|
507
446
|
|
508
447
|
[ Opcodes.local_get, leftPointer ],
|
509
448
|
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
@@ -516,11 +455,13 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
516
455
|
[ Opcodes.i32_add ],
|
517
456
|
|
518
457
|
// store length
|
519
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
458
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
520
459
|
|
521
460
|
// copy left
|
522
461
|
// dst = out pointer + length size
|
523
|
-
...
|
462
|
+
...pointer,
|
463
|
+
...number(ValtypeSize.i32, Valtype.i32),
|
464
|
+
[ Opcodes.i32_add ],
|
524
465
|
|
525
466
|
// src = left pointer + length size
|
526
467
|
[ Opcodes.local_get, leftPointer ],
|
@@ -533,7 +474,9 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
533
474
|
|
534
475
|
// copy right
|
535
476
|
// dst = out pointer + length size + left length * sizeof valtype
|
536
|
-
...
|
477
|
+
...pointer,
|
478
|
+
...number(ValtypeSize.i32, Valtype.i32),
|
479
|
+
[ Opcodes.i32_add ],
|
537
480
|
|
538
481
|
[ Opcodes.local_get, leftLength ],
|
539
482
|
...number(bytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
@@ -553,7 +496,8 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
553
496
|
[ ...Opcodes.memory_copy, 0x00, 0x00 ],
|
554
497
|
|
555
498
|
// return new string (page)
|
556
|
-
...
|
499
|
+
...pointer,
|
500
|
+
Opcodes.i32_from_u
|
557
501
|
];
|
558
502
|
};
|
559
503
|
|
@@ -669,10 +613,10 @@ const compareStrings = (scope, left, right, bytestrings = false) => {
|
|
669
613
|
};
|
670
614
|
|
671
615
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
672
|
-
if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
673
|
-
|
674
|
-
|
675
|
-
];
|
616
|
+
// if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
617
|
+
// ...wasm,
|
618
|
+
// ...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
|
619
|
+
// ];
|
676
620
|
// if (isIntOp(wasm[wasm.length - 1])) return [ ...wasm ];
|
677
621
|
|
678
622
|
// todo/perf: use knownType and custom bytecode here instead of typeSwitch
|
@@ -1054,7 +998,7 @@ const asmFuncToAsm = (func, scope) => {
|
|
1054
998
|
});
|
1055
999
|
};
|
1056
1000
|
|
1057
|
-
const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes = [], globalInits, returns, returnType, localNames = [], globalNames = [], data: _data = [], table = false }) => {
|
1001
|
+
const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes = [], globalInits = [], returns, returnType, localNames = [], globalNames = [], data: _data = [], table = false }) => {
|
1058
1002
|
const existing = funcs.find(x => x.name === name);
|
1059
1003
|
if (existing) return existing;
|
1060
1004
|
|
@@ -1068,7 +1012,7 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1068
1012
|
|
1069
1013
|
for (const x of _data) {
|
1070
1014
|
const copy = { ...x };
|
1071
|
-
copy.offset += pages.size * pageSize;
|
1015
|
+
if (copy.offset != null) copy.offset += pages.size * pageSize;
|
1072
1016
|
data.push(copy);
|
1073
1017
|
}
|
1074
1018
|
|
@@ -1091,9 +1035,9 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1091
1035
|
|
1092
1036
|
let baseGlobalIdx, i = 0;
|
1093
1037
|
for (const type of globalTypes) {
|
1094
|
-
if (baseGlobalIdx === undefined) baseGlobalIdx =
|
1038
|
+
if (baseGlobalIdx === undefined) baseGlobalIdx = globals['#ind'];
|
1095
1039
|
|
1096
|
-
globals[globalNames[i] ?? `${name}_global_${i}`] = { idx:
|
1040
|
+
globals[globalNames[i] ?? `${name}_global_${i}`] = { idx: globals['#ind']++, type, init: globalInits[i] ?? 0 };
|
1097
1041
|
i++;
|
1098
1042
|
}
|
1099
1043
|
|
@@ -1106,11 +1050,15 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1106
1050
|
}
|
1107
1051
|
}
|
1108
1052
|
|
1109
|
-
if (table)
|
1110
|
-
|
1111
|
-
inst.
|
1112
|
-
|
1053
|
+
if (table) {
|
1054
|
+
for (const inst of wasm) {
|
1055
|
+
if (inst[0] === Opcodes.i32_load16_u && inst.at(-1) === 'read_argc') {
|
1056
|
+
inst.splice(2, 99);
|
1057
|
+
inst.push(...unsignedLEB128(allocPage({}, 'func argc lut') * pageSize));
|
1058
|
+
}
|
1113
1059
|
}
|
1060
|
+
|
1061
|
+
funcs.table = true;
|
1114
1062
|
}
|
1115
1063
|
|
1116
1064
|
func.wasm = wasm;
|
@@ -1450,10 +1398,10 @@ const countLeftover = wasm => {
|
|
1450
1398
|
|
1451
1399
|
if (depth === 0)
|
1452
1400
|
if ([Opcodes.throw, Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1453
|
-
else if ([null, Opcodes.i32_eqz, Opcodes.i64_eqz, Opcodes.f64_ceil, Opcodes.f64_floor, Opcodes.f64_trunc, Opcodes.f64_nearest, Opcodes.f64_sqrt, Opcodes.local_tee, Opcodes.i32_wrap_i64, Opcodes.i64_extend_i32_s, Opcodes.i64_extend_i32_u, Opcodes.f32_demote_f64, Opcodes.f64_promote_f32, Opcodes.f64_convert_i32_s, Opcodes.f64_convert_i32_u, Opcodes.i32_clz, Opcodes.i32_ctz, Opcodes.i32_popcnt, Opcodes.f64_neg, Opcodes.end, Opcodes.i32_trunc_sat_f64_s[0], Opcodes.i32x4_extract_lane, Opcodes.i16x8_extract_lane, Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.i32_load8_u, Opcodes.i32_load8_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] <
|
1401
|
+
else if ([null, Opcodes.i32_eqz, Opcodes.i64_eqz, Opcodes.f64_ceil, Opcodes.f64_floor, Opcodes.f64_trunc, Opcodes.f64_nearest, Opcodes.f64_sqrt, Opcodes.local_tee, Opcodes.i32_wrap_i64, Opcodes.i64_extend_i32_s, Opcodes.i64_extend_i32_u, Opcodes.f32_demote_f64, Opcodes.f64_promote_f32, Opcodes.f64_convert_i32_s, Opcodes.f64_convert_i32_u, Opcodes.i32_clz, Opcodes.i32_ctz, Opcodes.i32_popcnt, Opcodes.f64_neg, Opcodes.end, Opcodes.i32_trunc_sat_f64_s[0], Opcodes.i32x4_extract_lane, Opcodes.i16x8_extract_lane, Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.i32_load8_u, Opcodes.i32_load8_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] < 0x04)) {}
|
1454
1402
|
else if ([Opcodes.local_get, Opcodes.global_get, Opcodes.f64_const, Opcodes.i32_const, Opcodes.i64_const, Opcodes.v128_const, Opcodes.memory_size].includes(inst[0])) count++;
|
1455
1403
|
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1456
|
-
else if (Opcodes.memory_copy[0]
|
1404
|
+
else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
|
1457
1405
|
else if (inst[0] === Opcodes.return) count = 0;
|
1458
1406
|
else if (inst[0] === Opcodes.call) {
|
1459
1407
|
let func = funcs.find(x => x.index === inst[1]);
|
@@ -1725,7 +1673,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1725
1673
|
}, generate(scope, decl.arguments[0] ?? DEFAULT_VALUE), getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE), protoLocal, protoLocal2, (length, itemType) => {
|
1726
1674
|
return makeArray(scope, {
|
1727
1675
|
rawElements: new Array(length)
|
1728
|
-
}, _global, _name, true, itemType);
|
1676
|
+
}, _global, _name, true, itemType, true);
|
1729
1677
|
}, () => {
|
1730
1678
|
optUnused = true;
|
1731
1679
|
return unusedValue;
|
@@ -2230,11 +2178,11 @@ const allocVar = (scope, name, global = false, type = true) => {
|
|
2230
2178
|
return target[name].idx;
|
2231
2179
|
}
|
2232
2180
|
|
2233
|
-
let idx = global ?
|
2181
|
+
let idx = global ? globals['#ind']++ : scope.localInd++;
|
2234
2182
|
target[name] = { idx, type: valtypeBinary };
|
2235
2183
|
|
2236
2184
|
if (type) {
|
2237
|
-
let typeIdx = global ?
|
2185
|
+
let typeIdx = global ? globals['#ind']++ : scope.localInd++;
|
2238
2186
|
target[name + '#type'] = { idx: typeIdx, type: Valtype.i32, name };
|
2239
2187
|
}
|
2240
2188
|
|
@@ -2327,24 +2275,10 @@ const generateVar = (scope, decl) => {
|
|
2327
2275
|
}
|
2328
2276
|
|
2329
2277
|
if (x.init) {
|
2330
|
-
|
2331
|
-
// // let a = function () { ... }
|
2332
|
-
// x.init.id = { name };
|
2333
|
-
|
2334
|
-
// const func = generateFunc(scope, x.init);
|
2335
|
-
|
2336
|
-
// out.push(
|
2337
|
-
// ...number(func.index - importedFuncs.length),
|
2338
|
-
// [ global ? Opcodes.global_set : Opcodes.local_set, idx ],
|
2339
|
-
|
2340
|
-
// ...setType(scope, name, TYPES.function)
|
2341
|
-
// );
|
2342
|
-
|
2343
|
-
// continue;
|
2344
|
-
// }
|
2278
|
+
const alreadyArray = scope.arrays?.get(name) != null;
|
2345
2279
|
|
2346
2280
|
const generated = generate(scope, x.init, global, name);
|
2347
|
-
if (scope.arrays?.get(name) != null) {
|
2281
|
+
if (!alreadyArray && scope.arrays?.get(name) != null) {
|
2348
2282
|
// hack to set local as pointer before
|
2349
2283
|
out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2350
2284
|
if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
|
@@ -2396,19 +2330,12 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2396
2330
|
|
2397
2331
|
// hack: .length setter
|
2398
2332
|
if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
|
2399
|
-
const name = decl.left.object.name;
|
2400
|
-
const pointer = scope.arrays?.get(name);
|
2401
|
-
|
2402
|
-
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2403
|
-
|
2404
2333
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2405
2334
|
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2406
2335
|
|
2407
2336
|
return [
|
2408
|
-
...(
|
2409
|
-
|
2410
|
-
Opcodes.i32_to_u
|
2411
|
-
]),
|
2337
|
+
...generate(scope, decl.left.object),
|
2338
|
+
Opcodes.i32_to_u,
|
2412
2339
|
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2413
2340
|
|
2414
2341
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
@@ -2419,7 +2346,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2419
2346
|
[ Opcodes.local_tee, newValueTmp ],
|
2420
2347
|
|
2421
2348
|
Opcodes.i32_to_u,
|
2422
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
2349
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2423
2350
|
|
2424
2351
|
[ Opcodes.local_get, newValueTmp ]
|
2425
2352
|
];
|
@@ -2427,21 +2354,14 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2427
2354
|
|
2428
2355
|
// arr[i]
|
2429
2356
|
if (decl.left.type === 'MemberExpression' && decl.left.computed) {
|
2430
|
-
const name = decl.left.object.name;
|
2431
|
-
const pointer = scope.arrays?.get(name);
|
2432
|
-
|
2433
|
-
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2434
|
-
|
2435
2357
|
const newValueTmp = localTmp(scope, '__member_setter_val_tmp');
|
2436
2358
|
const pointerTmp = op === '=' ? -1 : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2437
2359
|
|
2438
2360
|
return [
|
2439
2361
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2440
2362
|
[TYPES.array]: [
|
2441
|
-
...(
|
2442
|
-
|
2443
|
-
Opcodes.i32_to_u
|
2444
|
-
]),
|
2363
|
+
...generate(scope, decl.left.object),
|
2364
|
+
Opcodes.i32_to_u,
|
2445
2365
|
|
2446
2366
|
// get index as valtype
|
2447
2367
|
...generate(scope, decl.left.property),
|
@@ -2450,39 +2370,22 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2450
2370
|
// turn into byte offset by * valtypeSize (4 for i32, 8 for i64/f64)
|
2451
2371
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
2452
2372
|
[ Opcodes.i32_mul ],
|
2453
|
-
|
2373
|
+
[ Opcodes.i32_add ],
|
2454
2374
|
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2455
2375
|
|
2456
2376
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2457
2377
|
[ Opcodes.local_get, pointerTmp ],
|
2458
|
-
[ Opcodes.load, 0,
|
2378
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ]
|
2459
2379
|
], generate(scope, decl.right), [
|
2460
2380
|
[ Opcodes.local_get, pointerTmp ],
|
2461
|
-
[ Opcodes.i32_load8_u, 0,
|
2381
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2462
2382
|
], getNodeType(scope, decl.right), false, name, true)),
|
2463
2383
|
[ Opcodes.local_tee, newValueTmp ],
|
2464
2384
|
|
2465
|
-
[ Opcodes.store, 0,
|
2385
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2466
2386
|
],
|
2467
2387
|
|
2468
2388
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2469
|
-
|
2470
|
-
// [TYPES.string]: [
|
2471
|
-
// // turn into byte offset by * sizeof i16
|
2472
|
-
// ...number(ValtypeSize.i16, Valtype.i32),
|
2473
|
-
// [ Opcodes.i32_mul ],
|
2474
|
-
// ...(aotPointer ? [] : [ [ Opcodes.i32_add ] ]),
|
2475
|
-
// ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2476
|
-
|
2477
|
-
// ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2478
|
-
// [ Opcodes.local_get, pointerTmp ],
|
2479
|
-
// [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2480
|
-
// ], generate(scope, decl.right), number(TYPES.string, Valtype.i32), getNodeType(scope, decl.right))),
|
2481
|
-
// [ Opcodes.local_tee, newValueTmp ],
|
2482
|
-
|
2483
|
-
// Opcodes.i32_to_u,
|
2484
|
-
// [ StoreOps.i16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2485
|
-
// ]
|
2486
2389
|
}, Blocktype.void),
|
2487
2390
|
|
2488
2391
|
[ Opcodes.local_get, newValueTmp ]
|
@@ -2866,12 +2769,12 @@ const generateForOf = (scope, decl) => {
|
|
2866
2769
|
|
2867
2770
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2868
2771
|
// hack: this is naughty and will break things!
|
2869
|
-
let newOut = number(0, Valtype.
|
2772
|
+
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
2870
2773
|
if (pages.hasAnyString) {
|
2871
2774
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2872
2775
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2873
|
-
rawElements: new Array(
|
2874
|
-
}, isGlobal, leftName, true, 'i16');
|
2776
|
+
rawElements: new Array(0)
|
2777
|
+
}, isGlobal, leftName, true, 'i16', true);
|
2875
2778
|
}
|
2876
2779
|
|
2877
2780
|
// set type for local
|
@@ -2918,23 +2821,28 @@ const generateForOf = (scope, decl) => {
|
|
2918
2821
|
[TYPES.string]: [
|
2919
2822
|
...setType(scope, leftName, TYPES.string),
|
2920
2823
|
|
2921
|
-
[ Opcodes.loop, Blocktype.void ],
|
2922
|
-
|
2923
2824
|
// setup new/out array
|
2924
2825
|
...newOut,
|
2925
|
-
[ Opcodes.drop ],
|
2926
2826
|
|
2927
|
-
|
2827
|
+
// set length to 1
|
2828
|
+
...number(1, Valtype.i32),
|
2829
|
+
[ Opcodes.i32_store, 0, 0 ],
|
2830
|
+
|
2831
|
+
[ Opcodes.loop, Blocktype.void ],
|
2832
|
+
|
2833
|
+
// use as pointer for store later
|
2834
|
+
...newPointer,
|
2928
2835
|
|
2929
2836
|
// load current string ind {arg}
|
2930
2837
|
[ Opcodes.local_get, pointer ],
|
2931
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
2838
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2932
2839
|
|
2933
2840
|
// store to new string ind 0
|
2934
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
2841
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2935
2842
|
|
2936
2843
|
// return new string (page)
|
2937
|
-
...
|
2844
|
+
...newPointer,
|
2845
|
+
Opcodes.i32_from_u,
|
2938
2846
|
|
2939
2847
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2940
2848
|
|
@@ -2966,25 +2874,30 @@ const generateForOf = (scope, decl) => {
|
|
2966
2874
|
[TYPES.bytestring]: [
|
2967
2875
|
...setType(scope, leftName, TYPES.bytestring),
|
2968
2876
|
|
2969
|
-
[ Opcodes.loop, Blocktype.void ],
|
2970
|
-
|
2971
2877
|
// setup new/out array
|
2972
2878
|
...newOut,
|
2973
|
-
[ Opcodes.drop ],
|
2974
2879
|
|
2975
|
-
|
2880
|
+
// set length to 1
|
2881
|
+
...number(1, Valtype.i32),
|
2882
|
+
[ Opcodes.i32_store, 0, 0 ],
|
2883
|
+
|
2884
|
+
[ Opcodes.loop, Blocktype.void ],
|
2885
|
+
|
2886
|
+
// use as pointer for store later
|
2887
|
+
...newPointer,
|
2976
2888
|
|
2977
2889
|
// load current string ind {arg}
|
2978
2890
|
[ Opcodes.local_get, pointer ],
|
2979
2891
|
[ Opcodes.local_get, counter ],
|
2980
2892
|
[ Opcodes.i32_add ],
|
2981
|
-
[ Opcodes.i32_load8_u, 0,
|
2893
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
2982
2894
|
|
2983
2895
|
// store to new string ind 0
|
2984
|
-
[ Opcodes.i32_store8, 0,
|
2896
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
2985
2897
|
|
2986
2898
|
// return new string (page)
|
2987
|
-
...
|
2899
|
+
...newPointer,
|
2900
|
+
Opcodes.i32_from_u,
|
2988
2901
|
|
2989
2902
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2990
2903
|
|
@@ -3199,18 +3112,6 @@ const allocPage = (scope, reason, type) => {
|
|
3199
3112
|
scope.pages ??= new Map();
|
3200
3113
|
scope.pages.set(reason, { ind, type });
|
3201
3114
|
|
3202
|
-
if (Prefs.allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
|
3203
|
-
|
3204
|
-
return ind;
|
3205
|
-
};
|
3206
|
-
|
3207
|
-
// todo: add scope.pages
|
3208
|
-
const freePage = reason => {
|
3209
|
-
const { ind } = pages.get(reason);
|
3210
|
-
pages.delete(reason);
|
3211
|
-
|
3212
|
-
if (Prefs.allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
|
3213
|
-
|
3214
3115
|
return ind;
|
3215
3116
|
};
|
3216
3117
|
|
@@ -3248,39 +3149,58 @@ const compileBytes = (val, itemType) => {
|
|
3248
3149
|
}
|
3249
3150
|
};
|
3250
3151
|
|
3251
|
-
const
|
3252
|
-
|
3253
|
-
|
3254
|
-
|
3152
|
+
const makeData = (scope, elements, offset = null, itemType, initEmpty) => {
|
3153
|
+
const length = elements.length;
|
3154
|
+
|
3155
|
+
// if length is 0 memory/data will just be 0000... anyway
|
3156
|
+
if (length === 0) return false;
|
3157
|
+
|
3158
|
+
let bytes = compileBytes(length, 'i32');
|
3255
3159
|
|
3256
|
-
|
3160
|
+
if (!initEmpty) for (let i = 0; i < length; i++) {
|
3161
|
+
if (elements[i] == null) continue;
|
3162
|
+
|
3163
|
+
bytes.push(...compileBytes(elements[i], itemType));
|
3257
3164
|
}
|
3258
|
-
};
|
3259
3165
|
|
3260
|
-
const
|
3261
|
-
|
3166
|
+
const obj = { bytes };
|
3167
|
+
if (offset != null) obj.offset = offset;
|
3262
3168
|
|
3263
|
-
|
3169
|
+
const idx = data.push(obj) - 1;
|
3264
3170
|
|
3265
|
-
|
3266
|
-
|
3267
|
-
firstAssign = true;
|
3171
|
+
scope.data ??= [];
|
3172
|
+
scope.data.push(idx);
|
3268
3173
|
|
3269
|
-
|
3270
|
-
|
3174
|
+
return { idx, size: bytes.length };
|
3175
|
+
};
|
3176
|
+
|
3177
|
+
const printStaticStr = str => {
|
3178
|
+
const out = [];
|
3179
|
+
|
3180
|
+
for (let i = 0; i < str.length; i++) {
|
3181
|
+
out.push(
|
3182
|
+
// ...number(str.charCodeAt(i)),
|
3183
|
+
...number(str.charCodeAt(i), Valtype.i32),
|
3184
|
+
Opcodes.i32_from_u,
|
3185
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
3186
|
+
);
|
3187
|
+
}
|
3271
3188
|
|
3272
|
-
|
3273
|
-
|
3274
|
-
else page = allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType);
|
3189
|
+
return out;
|
3190
|
+
};
|
3275
3191
|
|
3276
|
-
|
3277
|
-
|
3278
|
-
|
3192
|
+
const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false, itemType = valtype, intOut = false, typed = false) => {
|
3193
|
+
if (itemType !== 'i16' && itemType !== 'i8') {
|
3194
|
+
pages.hasArray = true;
|
3195
|
+
} else {
|
3196
|
+
pages.hasAnyString = true;
|
3197
|
+
if (itemType === 'i8') pages.hasByteString = true;
|
3198
|
+
else pages.hasString = true;
|
3279
3199
|
}
|
3280
3200
|
|
3281
|
-
const
|
3201
|
+
const out = [];
|
3282
3202
|
|
3283
|
-
const
|
3203
|
+
const uniqueName = name === '$undeclared' ? name + randId() : name;
|
3284
3204
|
|
3285
3205
|
const useRawElements = !!decl.rawElements;
|
3286
3206
|
const elements = useRawElements ? decl.rawElements : decl.elements;
|
@@ -3288,46 +3208,81 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3288
3208
|
const valtype = itemTypeToValtype[itemType];
|
3289
3209
|
const length = elements.length;
|
3290
3210
|
|
3291
|
-
|
3292
|
-
|
3293
|
-
|
3294
|
-
|
3211
|
+
const allocated = allocator.alloc({ scope, pages, globals, asmFunc, funcIndex }, uniqueName, { itemType });
|
3212
|
+
|
3213
|
+
let pointer = allocated;
|
3214
|
+
if (allocator.constructor.name !== 'StaticAllocator') {
|
3215
|
+
// const tmp = localTmp(scope, '#makearray_pointer' + uniqueName, Valtype.i32);
|
3216
|
+
const tmp = localTmp(scope, '#makearray_pointer' + name, Valtype.i32);
|
3217
|
+
out.push(
|
3218
|
+
...allocated,
|
3219
|
+
[ Opcodes.local_set, tmp ]
|
3220
|
+
);
|
3221
|
+
|
3222
|
+
if (Prefs.runtimeAllocLog) out.push(
|
3223
|
+
...printStaticStr(`${name}: `),
|
3295
3224
|
|
3296
|
-
|
3297
|
-
|
3225
|
+
[ Opcodes.local_get, tmp ],
|
3226
|
+
Opcodes.i32_from_u,
|
3227
|
+
[ Opcodes.call, 0 ],
|
3298
3228
|
|
3299
|
-
|
3229
|
+
...number(10),
|
3230
|
+
[ Opcodes.call, 1 ]
|
3231
|
+
);
|
3232
|
+
|
3233
|
+
pointer = [ [ Opcodes.local_get, tmp ] ];
|
3234
|
+
|
3235
|
+
if (Prefs.data && useRawElements) {
|
3236
|
+
const data = makeData(scope, elements, null, itemType, initEmpty);
|
3237
|
+
if (data) {
|
3238
|
+
// init data
|
3239
|
+
out.push(
|
3240
|
+
...pointer,
|
3241
|
+
...number(0, Valtype.i32),
|
3242
|
+
...number(data.size, Valtype.i32),
|
3243
|
+
[ ...Opcodes.memory_init, ...unsignedLEB128(data.idx), 0 ]
|
3244
|
+
);
|
3300
3245
|
}
|
3301
3246
|
|
3302
|
-
|
3303
|
-
|
3304
|
-
|
3305
|
-
|
3247
|
+
// return pointer in out
|
3248
|
+
out.push(
|
3249
|
+
...pointer,
|
3250
|
+
...(!intOut ? [ Opcodes.i32_from_u ] : [])
|
3251
|
+
);
|
3306
3252
|
|
3307
|
-
|
3308
|
-
scope.data.push(ind);
|
3253
|
+
return [ out, pointer ];
|
3309
3254
|
}
|
3255
|
+
} else {
|
3256
|
+
const rawPtr = read_signedLEB128(pointer[0].slice(1));
|
3310
3257
|
|
3311
|
-
|
3312
|
-
|
3258
|
+
scope.arrays ??= new Map();
|
3259
|
+
const firstAssign = !scope.arrays.has(uniqueName);
|
3260
|
+
if (firstAssign) scope.arrays.set(uniqueName, rawPtr);
|
3313
3261
|
|
3314
|
-
|
3315
|
-
|
3262
|
+
if (Prefs.data && firstAssign && useRawElements) {
|
3263
|
+
makeData(scope, elements, rawPtr, itemType, initEmpty);
|
3316
3264
|
|
3317
|
-
|
3318
|
-
|
3319
|
-
|
3320
|
-
|
3321
|
-
|
3322
|
-
|
3323
|
-
)
|
3265
|
+
// local value as pointer
|
3266
|
+
return [ number(rawPtr, intOut ? Valtype.i32 : valtypeBinary), pointer ];
|
3267
|
+
}
|
3268
|
+
|
3269
|
+
const local = global ? globals[name] : scope.locals[name];
|
3270
|
+
const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
|
3271
|
+
if (pointerTmp != null) {
|
3272
|
+
out.push(
|
3273
|
+
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
3274
|
+
Opcodes.i32_to_u,
|
3275
|
+
[ Opcodes.local_set, pointerTmp ]
|
3276
|
+
);
|
3277
|
+
|
3278
|
+
pointer = [ [ Opcodes.local_get, pointerTmp ] ];
|
3279
|
+
}
|
3324
3280
|
}
|
3325
3281
|
|
3326
|
-
const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
|
3327
3282
|
|
3328
3283
|
// store length
|
3329
3284
|
out.push(
|
3330
|
-
...
|
3285
|
+
...pointer,
|
3331
3286
|
...number(length, Valtype.i32),
|
3332
3287
|
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
|
3333
3288
|
);
|
@@ -3339,11 +3294,11 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3339
3294
|
|
3340
3295
|
const offset = ValtypeSize.i32 + i * sizePerEl;
|
3341
3296
|
out.push(
|
3342
|
-
...
|
3297
|
+
...pointer,
|
3343
3298
|
...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
|
3344
3299
|
[ storeOp, 0, ...unsignedLEB128(offset) ],
|
3345
3300
|
...(!typed ? [] : [ // typed presumes !useRawElements
|
3346
|
-
...
|
3301
|
+
...pointer,
|
3347
3302
|
...getNodeType(scope, elements[i]),
|
3348
3303
|
[ Opcodes.i32_store8, 0, ...unsignedLEB128(offset + ValtypeSize[itemType]) ]
|
3349
3304
|
])
|
@@ -3351,12 +3306,13 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3351
3306
|
}
|
3352
3307
|
|
3353
3308
|
// local value as pointer
|
3354
|
-
out.push(...
|
3309
|
+
out.push(...pointer);
|
3310
|
+
if (!intOut) out.push(Opcodes.i32_from_u);
|
3355
3311
|
|
3356
3312
|
return [ out, pointer ];
|
3357
3313
|
};
|
3358
3314
|
|
3359
|
-
const storeArray = (scope, array, index, element
|
3315
|
+
const storeArray = (scope, array, index, element) => {
|
3360
3316
|
if (!Array.isArray(element)) element = generate(scope, element);
|
3361
3317
|
if (typeof index === 'number') index = number(index);
|
3362
3318
|
|
@@ -3368,26 +3324,25 @@ const storeArray = (scope, array, index, element, aotPointer = null) => {
|
|
3368
3324
|
Opcodes.i32_to_u,
|
3369
3325
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3370
3326
|
[ Opcodes.i32_mul ],
|
3371
|
-
|
3372
|
-
|
3373
|
-
|
3374
|
-
|
3375
|
-
]),
|
3327
|
+
|
3328
|
+
...array,
|
3329
|
+
Opcodes.i32_to_u,
|
3330
|
+
[ Opcodes.i32_add ],
|
3376
3331
|
[ Opcodes.local_set, offset ],
|
3377
3332
|
|
3378
3333
|
// store value
|
3379
3334
|
[ Opcodes.local_get, offset ],
|
3380
3335
|
...generate(scope, element),
|
3381
|
-
[ Opcodes.store, 0,
|
3336
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
3382
3337
|
|
3383
3338
|
// store type
|
3384
3339
|
[ Opcodes.local_get, offset ],
|
3385
3340
|
...getNodeType(scope, element),
|
3386
|
-
[ Opcodes.i32_store8, 0,
|
3341
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3387
3342
|
];
|
3388
3343
|
};
|
3389
3344
|
|
3390
|
-
const loadArray = (scope, array, index
|
3345
|
+
const loadArray = (scope, array, index) => {
|
3391
3346
|
if (typeof index === 'number') index = number(index);
|
3392
3347
|
|
3393
3348
|
const offset = localTmp(scope, '#loadArray_offset', Valtype.i32);
|
@@ -3398,20 +3353,19 @@ const loadArray = (scope, array, index, aotPointer = null) => {
|
|
3398
3353
|
Opcodes.i32_to_u,
|
3399
3354
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3400
3355
|
[ Opcodes.i32_mul ],
|
3401
|
-
|
3402
|
-
|
3403
|
-
|
3404
|
-
|
3405
|
-
]),
|
3356
|
+
|
3357
|
+
...array,
|
3358
|
+
Opcodes.i32_to_u,
|
3359
|
+
[ Opcodes.i32_add ],
|
3406
3360
|
[ Opcodes.local_set, offset ],
|
3407
3361
|
|
3408
3362
|
// load value
|
3409
3363
|
[ Opcodes.local_get, offset ],
|
3410
|
-
[ Opcodes.load, 0,
|
3364
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
3411
3365
|
|
3412
3366
|
// load type
|
3413
3367
|
[ Opcodes.local_get, offset ],
|
3414
|
-
[ Opcodes.i32_load8_u, 0,
|
3368
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3415
3369
|
];
|
3416
3370
|
};
|
3417
3371
|
|
@@ -3443,7 +3397,7 @@ const makeString = (scope, str, global = false, name = '$undeclared', forceBytes
|
|
3443
3397
|
};
|
3444
3398
|
|
3445
3399
|
const generateArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false) => {
|
3446
|
-
return makeArray(scope, decl, global, name, initEmpty, valtype, true)[0];
|
3400
|
+
return makeArray(scope, decl, global, name, initEmpty, valtype, false, true)[0];
|
3447
3401
|
};
|
3448
3402
|
|
3449
3403
|
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
@@ -3462,9 +3416,6 @@ const withType = (scope, wasm, type) => [
|
|
3462
3416
|
|
3463
3417
|
const generateMember = (scope, decl, _global, _name) => {
|
3464
3418
|
const name = decl.object.name;
|
3465
|
-
const pointer = scope.arrays?.get(name);
|
3466
|
-
|
3467
|
-
const aotPointer = Prefs.aotPointerOpt && pointer;
|
3468
3419
|
|
3469
3420
|
// hack: .name
|
3470
3421
|
if (decl.property.name === 'name') {
|
@@ -3505,12 +3456,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3505
3456
|
if (Prefs.fastLength) {
|
3506
3457
|
// presume valid length object
|
3507
3458
|
return [
|
3508
|
-
...(
|
3509
|
-
|
3510
|
-
Opcodes.i32_to_u
|
3511
|
-
]),
|
3459
|
+
...generate(scope, decl.object),
|
3460
|
+
Opcodes.i32_to_u,
|
3512
3461
|
|
3513
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3462
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3514
3463
|
Opcodes.i32_from_u
|
3515
3464
|
];
|
3516
3465
|
}
|
@@ -3519,12 +3468,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3519
3468
|
const known = knownType(scope, type);
|
3520
3469
|
if (known != null) {
|
3521
3470
|
if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(known)) return [
|
3522
|
-
...(
|
3523
|
-
|
3524
|
-
Opcodes.i32_to_u
|
3525
|
-
]),
|
3471
|
+
...generate(scope, decl.object),
|
3472
|
+
Opcodes.i32_to_u,
|
3526
3473
|
|
3527
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3474
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3528
3475
|
Opcodes.i32_from_u
|
3529
3476
|
];
|
3530
3477
|
|
@@ -3534,12 +3481,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3534
3481
|
return [
|
3535
3482
|
...typeIsOneOf(getNodeType(scope, decl.object), [ TYPES.string, TYPES.bytestring, TYPES.array ]),
|
3536
3483
|
[ Opcodes.if, valtypeBinary ],
|
3537
|
-
...(
|
3538
|
-
|
3539
|
-
Opcodes.i32_to_u
|
3540
|
-
]),
|
3484
|
+
...generate(scope, decl.object),
|
3485
|
+
Opcodes.i32_to_u,
|
3541
3486
|
|
3542
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3487
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3543
3488
|
Opcodes.i32_from_u,
|
3544
3489
|
|
3545
3490
|
...setLastType(scope, TYPES.number),
|
@@ -3582,25 +3527,29 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3582
3527
|
|
3583
3528
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3584
3529
|
// hack: this is naughty and will break things!
|
3585
|
-
let newOut = number(0,
|
3530
|
+
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3586
3531
|
if (pages.hasAnyString) {
|
3532
|
+
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3587
3533
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3588
|
-
rawElements: new Array(
|
3589
|
-
}, _global, _name, true, 'i16');
|
3534
|
+
rawElements: new Array(0)
|
3535
|
+
}, _global, _name, true, 'i16', true);
|
3590
3536
|
}
|
3591
3537
|
|
3592
3538
|
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3593
3539
|
[TYPES.array]: [
|
3594
|
-
...loadArray(scope, object, property
|
3540
|
+
...loadArray(scope, object, property),
|
3595
3541
|
...setLastType(scope)
|
3596
3542
|
],
|
3597
|
-
|
3598
3543
|
[TYPES.string]: [
|
3599
3544
|
// setup new/out array
|
3600
3545
|
...newOut,
|
3601
|
-
[ Opcodes.drop ],
|
3602
3546
|
|
3603
|
-
|
3547
|
+
// set length to 1
|
3548
|
+
...number(1, Valtype.i32),
|
3549
|
+
[ Opcodes.i32_store, 0, 0 ],
|
3550
|
+
|
3551
|
+
// use as pointer for store later
|
3552
|
+
...newPointer,
|
3604
3553
|
|
3605
3554
|
...property,
|
3606
3555
|
Opcodes.i32_to_u,
|
@@ -3608,46 +3557,48 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3608
3557
|
...number(ValtypeSize.i16, Valtype.i32),
|
3609
3558
|
[ Opcodes.i32_mul ],
|
3610
3559
|
|
3611
|
-
...
|
3612
|
-
|
3613
|
-
|
3614
|
-
[ Opcodes.i32_add ]
|
3615
|
-
]),
|
3560
|
+
...object,
|
3561
|
+
Opcodes.i32_to_u,
|
3562
|
+
[ Opcodes.i32_add ],
|
3616
3563
|
|
3617
3564
|
// load current string ind {arg}
|
3618
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
3565
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3619
3566
|
|
3620
3567
|
// store to new string ind 0
|
3621
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
3568
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3622
3569
|
|
3623
3570
|
// return new string (page)
|
3624
|
-
...
|
3571
|
+
...newPointer,
|
3572
|
+
Opcodes.i32_from_u,
|
3625
3573
|
...setLastType(scope, TYPES.string)
|
3626
3574
|
],
|
3627
3575
|
[TYPES.bytestring]: [
|
3628
3576
|
// setup new/out array
|
3629
3577
|
...newOut,
|
3630
|
-
[ Opcodes.drop ],
|
3631
3578
|
|
3632
|
-
|
3579
|
+
// set length to 1
|
3580
|
+
...number(1, Valtype.i32),
|
3581
|
+
[ Opcodes.i32_store, 0, 0 ],
|
3582
|
+
|
3583
|
+
// use as pointer for store later
|
3584
|
+
...newPointer,
|
3633
3585
|
|
3634
3586
|
...property,
|
3635
3587
|
Opcodes.i32_to_u,
|
3636
3588
|
|
3637
|
-
...
|
3638
|
-
|
3639
|
-
|
3640
|
-
[ Opcodes.i32_add ]
|
3641
|
-
]),
|
3589
|
+
...object,
|
3590
|
+
Opcodes.i32_to_u,
|
3591
|
+
[ Opcodes.i32_add ],
|
3642
3592
|
|
3643
3593
|
// load current string ind {arg}
|
3644
|
-
[ Opcodes.i32_load8_u, 0,
|
3594
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
3645
3595
|
|
3646
3596
|
// store to new string ind 0
|
3647
|
-
[ Opcodes.i32_store8, 0,
|
3597
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
3648
3598
|
|
3649
3599
|
// return new string (page)
|
3650
|
-
...
|
3600
|
+
...newPointer,
|
3601
|
+
Opcodes.i32_from_u,
|
3651
3602
|
...setLastType(scope, TYPES.bytestring)
|
3652
3603
|
],
|
3653
3604
|
|
@@ -3792,9 +3743,9 @@ const internalConstrs = {
|
|
3792
3743
|
|
3793
3744
|
// new Array(n)
|
3794
3745
|
|
3795
|
-
const [ , pointer ] = makeArray(scope, {
|
3746
|
+
const [ out, pointer ] = makeArray(scope, {
|
3796
3747
|
rawElements: new Array(0)
|
3797
|
-
}, global, name, true);
|
3748
|
+
}, global, name, true, undefined, true);
|
3798
3749
|
|
3799
3750
|
const arg = decl.arguments[0] ?? DEFAULT_VALUE;
|
3800
3751
|
|
@@ -3803,12 +3754,13 @@ const internalConstrs = {
|
|
3803
3754
|
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeThrow', 'Invalid array length', true);
|
3804
3755
|
|
3805
3756
|
return [
|
3806
|
-
...
|
3757
|
+
...out,
|
3807
3758
|
...generate(scope, arg, global, name),
|
3808
3759
|
Opcodes.i32_to_u,
|
3809
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
3760
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3810
3761
|
|
3811
|
-
...
|
3762
|
+
...pointer,
|
3763
|
+
Opcodes.i32_from_u
|
3812
3764
|
];
|
3813
3765
|
},
|
3814
3766
|
type: TYPES.array,
|
@@ -3957,8 +3909,9 @@ const internalConstrs = {
|
|
3957
3909
|
};
|
3958
3910
|
|
3959
3911
|
export default program => {
|
3960
|
-
globals = {
|
3961
|
-
|
3912
|
+
globals = {
|
3913
|
+
['#ind']: 0
|
3914
|
+
};
|
3962
3915
|
tags = [];
|
3963
3916
|
exceptions = [];
|
3964
3917
|
funcs = [];
|
@@ -3991,6 +3944,7 @@ export default program => {
|
|
3991
3944
|
builtinFuncs = new BuiltinFuncs();
|
3992
3945
|
builtinVars = new BuiltinVars();
|
3993
3946
|
prototypeFuncs = new PrototypeFuncs();
|
3947
|
+
allocator = makeAllocator(Prefs.allocator ?? 'static');
|
3994
3948
|
|
3995
3949
|
program.id = { name: 'main' };
|
3996
3950
|
|
@@ -4033,6 +3987,8 @@ export default program => {
|
|
4033
3987
|
else main.returns = [];
|
4034
3988
|
}
|
4035
3989
|
|
3990
|
+
delete globals['#ind'];
|
3991
|
+
|
4036
3992
|
// if blank main func and other exports, remove it
|
4037
3993
|
if (main.wasm.length === 0 && funcs.reduce((acc, x) => acc + (x.export ? 1 : 0), 0) > 1) funcs.splice(main.index - importedFuncs.length, 1);
|
4038
3994
|
|