porffor 0.16.0-6572d1c74 → 0.16.0-7143cc59c
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/CONTRIBUTING.md +1 -1
- package/README.md +3 -4
- 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 +253 -300
- package/compiler/cyclone.js +11 -11
- package/compiler/generated_builtins.js +46 -46
- package/compiler/index.js +30 -3
- package/compiler/opt.js +7 -5
- package/compiler/parse.js +1 -7
- package/compiler/pgo.js +13 -8
- package/compiler/precompile.js +12 -7
- package/compiler/prefs.js +2 -3
- package/compiler/prototype.js +34 -43
- package/compiler/wasmSpec.js +2 -2
- package/compiler/wrap.js +3 -2
- package/package.json +3 -5
- package/runner/index.js +13 -3
- 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;
|
@@ -2115,7 +2063,6 @@ const brTable = (input, bc, returns) => {
|
|
2115
2063
|
}
|
2116
2064
|
|
2117
2065
|
for (let i = 0; i < count; i++) {
|
2118
|
-
// if (i === 0) out.push([ Opcodes.block, returns, 'br table start' ]);
|
2119
2066
|
if (i === 0) out.push([ Opcodes.block, returns ]);
|
2120
2067
|
else out.push([ Opcodes.block, Blocktype.void ]);
|
2121
2068
|
}
|
@@ -2149,10 +2096,8 @@ const brTable = (input, bc, returns) => {
|
|
2149
2096
|
[ Opcodes.br_table, ...encodeVector(table), 0 ]
|
2150
2097
|
);
|
2151
2098
|
|
2152
|
-
//
|
2153
|
-
// (
|
2154
|
-
// dm me and if you are correct and the first person
|
2155
|
-
// I will somehow shout you out or something
|
2099
|
+
// sort the wrong way and then reverse
|
2100
|
+
// so strings ('default') are at the start before any numbers
|
2156
2101
|
const orderedBc = keys.sort((a, b) => b - a).reverse();
|
2157
2102
|
|
2158
2103
|
br = count - 1;
|
@@ -2178,7 +2123,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
|
2178
2123
|
return bc[known] ?? bc.default;
|
2179
2124
|
}
|
2180
2125
|
|
2181
|
-
if (Prefs.
|
2126
|
+
if (Prefs.typeswitchBrtable)
|
2182
2127
|
return brTable(type, bc, returns);
|
2183
2128
|
|
2184
2129
|
const tmp = localTmp(scope, '#typeswitch_tmp' + (Prefs.typeswitchUniqueTmp ? randId() : ''), Valtype.i32);
|
@@ -2233,11 +2178,11 @@ const allocVar = (scope, name, global = false, type = true) => {
|
|
2233
2178
|
return target[name].idx;
|
2234
2179
|
}
|
2235
2180
|
|
2236
|
-
let idx = global ?
|
2181
|
+
let idx = global ? globals['#ind']++ : scope.localInd++;
|
2237
2182
|
target[name] = { idx, type: valtypeBinary };
|
2238
2183
|
|
2239
2184
|
if (type) {
|
2240
|
-
let typeIdx = global ?
|
2185
|
+
let typeIdx = global ? globals['#ind']++ : scope.localInd++;
|
2241
2186
|
target[name + '#type'] = { idx: typeIdx, type: Valtype.i32, name };
|
2242
2187
|
}
|
2243
2188
|
|
@@ -2330,24 +2275,10 @@ const generateVar = (scope, decl) => {
|
|
2330
2275
|
}
|
2331
2276
|
|
2332
2277
|
if (x.init) {
|
2333
|
-
|
2334
|
-
// // let a = function () { ... }
|
2335
|
-
// x.init.id = { name };
|
2336
|
-
|
2337
|
-
// const func = generateFunc(scope, x.init);
|
2338
|
-
|
2339
|
-
// out.push(
|
2340
|
-
// ...number(func.index - importedFuncs.length),
|
2341
|
-
// [ global ? Opcodes.global_set : Opcodes.local_set, idx ],
|
2342
|
-
|
2343
|
-
// ...setType(scope, name, TYPES.function)
|
2344
|
-
// );
|
2345
|
-
|
2346
|
-
// continue;
|
2347
|
-
// }
|
2278
|
+
const alreadyArray = scope.arrays?.get(name) != null;
|
2348
2279
|
|
2349
2280
|
const generated = generate(scope, x.init, global, name);
|
2350
|
-
if (scope.arrays?.get(name) != null) {
|
2281
|
+
if (!alreadyArray && scope.arrays?.get(name) != null) {
|
2351
2282
|
// hack to set local as pointer before
|
2352
2283
|
out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2353
2284
|
if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
|
@@ -2399,19 +2330,12 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2399
2330
|
|
2400
2331
|
// hack: .length setter
|
2401
2332
|
if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
|
2402
|
-
const name = decl.left.object.name;
|
2403
|
-
const pointer = scope.arrays?.get(name);
|
2404
|
-
|
2405
|
-
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2406
|
-
|
2407
2333
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2408
2334
|
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2409
2335
|
|
2410
2336
|
return [
|
2411
|
-
...(
|
2412
|
-
|
2413
|
-
Opcodes.i32_to_u
|
2414
|
-
]),
|
2337
|
+
...generate(scope, decl.left.object),
|
2338
|
+
Opcodes.i32_to_u,
|
2415
2339
|
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2416
2340
|
|
2417
2341
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
@@ -2422,7 +2346,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2422
2346
|
[ Opcodes.local_tee, newValueTmp ],
|
2423
2347
|
|
2424
2348
|
Opcodes.i32_to_u,
|
2425
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
2349
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2426
2350
|
|
2427
2351
|
[ Opcodes.local_get, newValueTmp ]
|
2428
2352
|
];
|
@@ -2430,21 +2354,14 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2430
2354
|
|
2431
2355
|
// arr[i]
|
2432
2356
|
if (decl.left.type === 'MemberExpression' && decl.left.computed) {
|
2433
|
-
const name = decl.left.object.name;
|
2434
|
-
const pointer = scope.arrays?.get(name);
|
2435
|
-
|
2436
|
-
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2437
|
-
|
2438
2357
|
const newValueTmp = localTmp(scope, '__member_setter_val_tmp');
|
2439
2358
|
const pointerTmp = op === '=' ? -1 : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2440
2359
|
|
2441
2360
|
return [
|
2442
2361
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2443
2362
|
[TYPES.array]: [
|
2444
|
-
...(
|
2445
|
-
|
2446
|
-
Opcodes.i32_to_u
|
2447
|
-
]),
|
2363
|
+
...generate(scope, decl.left.object),
|
2364
|
+
Opcodes.i32_to_u,
|
2448
2365
|
|
2449
2366
|
// get index as valtype
|
2450
2367
|
...generate(scope, decl.left.property),
|
@@ -2453,39 +2370,22 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2453
2370
|
// turn into byte offset by * valtypeSize (4 for i32, 8 for i64/f64)
|
2454
2371
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
2455
2372
|
[ Opcodes.i32_mul ],
|
2456
|
-
|
2373
|
+
[ Opcodes.i32_add ],
|
2457
2374
|
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2458
2375
|
|
2459
2376
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2460
2377
|
[ Opcodes.local_get, pointerTmp ],
|
2461
|
-
[ Opcodes.load, 0,
|
2378
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ]
|
2462
2379
|
], generate(scope, decl.right), [
|
2463
2380
|
[ Opcodes.local_get, pointerTmp ],
|
2464
|
-
[ Opcodes.i32_load8_u, 0,
|
2381
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2465
2382
|
], getNodeType(scope, decl.right), false, name, true)),
|
2466
2383
|
[ Opcodes.local_tee, newValueTmp ],
|
2467
2384
|
|
2468
|
-
[ Opcodes.store, 0,
|
2385
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2469
2386
|
],
|
2470
2387
|
|
2471
2388
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2472
|
-
|
2473
|
-
// [TYPES.string]: [
|
2474
|
-
// // turn into byte offset by * sizeof i16
|
2475
|
-
// ...number(ValtypeSize.i16, Valtype.i32),
|
2476
|
-
// [ Opcodes.i32_mul ],
|
2477
|
-
// ...(aotPointer ? [] : [ [ Opcodes.i32_add ] ]),
|
2478
|
-
// ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2479
|
-
|
2480
|
-
// ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2481
|
-
// [ Opcodes.local_get, pointerTmp ],
|
2482
|
-
// [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2483
|
-
// ], generate(scope, decl.right), number(TYPES.string, Valtype.i32), getNodeType(scope, decl.right))),
|
2484
|
-
// [ Opcodes.local_tee, newValueTmp ],
|
2485
|
-
|
2486
|
-
// Opcodes.i32_to_u,
|
2487
|
-
// [ StoreOps.i16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2488
|
-
// ]
|
2489
2389
|
}, Blocktype.void),
|
2490
2390
|
|
2491
2391
|
[ Opcodes.local_get, newValueTmp ]
|
@@ -2869,12 +2769,12 @@ const generateForOf = (scope, decl) => {
|
|
2869
2769
|
|
2870
2770
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2871
2771
|
// hack: this is naughty and will break things!
|
2872
|
-
let newOut = number(0, Valtype.
|
2772
|
+
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
2873
2773
|
if (pages.hasAnyString) {
|
2874
2774
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2875
2775
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2876
|
-
rawElements: new Array(
|
2877
|
-
}, isGlobal, leftName, true, 'i16');
|
2776
|
+
rawElements: new Array(0)
|
2777
|
+
}, isGlobal, leftName, true, 'i16', true);
|
2878
2778
|
}
|
2879
2779
|
|
2880
2780
|
// set type for local
|
@@ -2921,23 +2821,28 @@ const generateForOf = (scope, decl) => {
|
|
2921
2821
|
[TYPES.string]: [
|
2922
2822
|
...setType(scope, leftName, TYPES.string),
|
2923
2823
|
|
2924
|
-
[ Opcodes.loop, Blocktype.void ],
|
2925
|
-
|
2926
2824
|
// setup new/out array
|
2927
2825
|
...newOut,
|
2928
|
-
[ Opcodes.drop ],
|
2929
2826
|
|
2930
|
-
|
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,
|
2931
2835
|
|
2932
2836
|
// load current string ind {arg}
|
2933
2837
|
[ Opcodes.local_get, pointer ],
|
2934
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
2838
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2935
2839
|
|
2936
2840
|
// store to new string ind 0
|
2937
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
2841
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2938
2842
|
|
2939
2843
|
// return new string (page)
|
2940
|
-
...
|
2844
|
+
...newPointer,
|
2845
|
+
Opcodes.i32_from_u,
|
2941
2846
|
|
2942
2847
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2943
2848
|
|
@@ -2969,25 +2874,30 @@ const generateForOf = (scope, decl) => {
|
|
2969
2874
|
[TYPES.bytestring]: [
|
2970
2875
|
...setType(scope, leftName, TYPES.bytestring),
|
2971
2876
|
|
2972
|
-
[ Opcodes.loop, Blocktype.void ],
|
2973
|
-
|
2974
2877
|
// setup new/out array
|
2975
2878
|
...newOut,
|
2976
|
-
[ Opcodes.drop ],
|
2977
2879
|
|
2978
|
-
|
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,
|
2979
2888
|
|
2980
2889
|
// load current string ind {arg}
|
2981
2890
|
[ Opcodes.local_get, pointer ],
|
2982
2891
|
[ Opcodes.local_get, counter ],
|
2983
2892
|
[ Opcodes.i32_add ],
|
2984
|
-
[ Opcodes.i32_load8_u, 0,
|
2893
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
2985
2894
|
|
2986
2895
|
// store to new string ind 0
|
2987
|
-
[ Opcodes.i32_store8, 0,
|
2896
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
2988
2897
|
|
2989
2898
|
// return new string (page)
|
2990
|
-
...
|
2899
|
+
...newPointer,
|
2900
|
+
Opcodes.i32_from_u,
|
2991
2901
|
|
2992
2902
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2993
2903
|
|
@@ -3202,18 +3112,6 @@ const allocPage = (scope, reason, type) => {
|
|
3202
3112
|
scope.pages ??= new Map();
|
3203
3113
|
scope.pages.set(reason, { ind, type });
|
3204
3114
|
|
3205
|
-
if (Prefs.allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
|
3206
|
-
|
3207
|
-
return ind;
|
3208
|
-
};
|
3209
|
-
|
3210
|
-
// todo: add scope.pages
|
3211
|
-
const freePage = reason => {
|
3212
|
-
const { ind } = pages.get(reason);
|
3213
|
-
pages.delete(reason);
|
3214
|
-
|
3215
|
-
if (Prefs.allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
|
3216
|
-
|
3217
3115
|
return ind;
|
3218
3116
|
};
|
3219
3117
|
|
@@ -3251,39 +3149,58 @@ const compileBytes = (val, itemType) => {
|
|
3251
3149
|
}
|
3252
3150
|
};
|
3253
3151
|
|
3254
|
-
const
|
3255
|
-
|
3256
|
-
|
3257
|
-
|
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');
|
3258
3159
|
|
3259
|
-
|
3160
|
+
if (!initEmpty) for (let i = 0; i < length; i++) {
|
3161
|
+
if (elements[i] == null) continue;
|
3162
|
+
|
3163
|
+
bytes.push(...compileBytes(elements[i], itemType));
|
3260
3164
|
}
|
3261
|
-
};
|
3262
3165
|
|
3263
|
-
const
|
3264
|
-
|
3166
|
+
const obj = { bytes };
|
3167
|
+
if (offset != null) obj.offset = offset;
|
3265
3168
|
|
3266
|
-
|
3169
|
+
const idx = data.push(obj) - 1;
|
3267
3170
|
|
3268
|
-
|
3269
|
-
|
3270
|
-
firstAssign = true;
|
3171
|
+
scope.data ??= [];
|
3172
|
+
scope.data.push(idx);
|
3271
3173
|
|
3272
|
-
|
3273
|
-
|
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
|
+
}
|
3274
3188
|
|
3275
|
-
|
3276
|
-
|
3277
|
-
else page = allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType);
|
3189
|
+
return out;
|
3190
|
+
};
|
3278
3191
|
|
3279
|
-
|
3280
|
-
|
3281
|
-
|
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;
|
3282
3199
|
}
|
3283
3200
|
|
3284
|
-
const
|
3201
|
+
const out = [];
|
3285
3202
|
|
3286
|
-
const
|
3203
|
+
const uniqueName = name === '$undeclared' ? name + randId() : name;
|
3287
3204
|
|
3288
3205
|
const useRawElements = !!decl.rawElements;
|
3289
3206
|
const elements = useRawElements ? decl.rawElements : decl.elements;
|
@@ -3291,46 +3208,81 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3291
3208
|
const valtype = itemTypeToValtype[itemType];
|
3292
3209
|
const length = elements.length;
|
3293
3210
|
|
3294
|
-
|
3295
|
-
|
3296
|
-
|
3297
|
-
|
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}: `),
|
3298
3224
|
|
3299
|
-
|
3300
|
-
|
3225
|
+
[ Opcodes.local_get, tmp ],
|
3226
|
+
Opcodes.i32_from_u,
|
3227
|
+
[ Opcodes.call, 0 ],
|
3301
3228
|
|
3302
|
-
|
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
|
+
);
|
3303
3245
|
}
|
3304
3246
|
|
3305
|
-
|
3306
|
-
|
3307
|
-
|
3308
|
-
|
3247
|
+
// return pointer in out
|
3248
|
+
out.push(
|
3249
|
+
...pointer,
|
3250
|
+
...(!intOut ? [ Opcodes.i32_from_u ] : [])
|
3251
|
+
);
|
3309
3252
|
|
3310
|
-
|
3311
|
-
scope.data.push(ind);
|
3253
|
+
return [ out, pointer ];
|
3312
3254
|
}
|
3255
|
+
} else {
|
3256
|
+
const rawPtr = read_signedLEB128(pointer[0].slice(1));
|
3313
3257
|
|
3314
|
-
|
3315
|
-
|
3258
|
+
scope.arrays ??= new Map();
|
3259
|
+
const firstAssign = !scope.arrays.has(uniqueName);
|
3260
|
+
if (firstAssign) scope.arrays.set(uniqueName, rawPtr);
|
3316
3261
|
|
3317
|
-
|
3318
|
-
|
3262
|
+
if (Prefs.data && firstAssign && useRawElements) {
|
3263
|
+
makeData(scope, elements, rawPtr, itemType, initEmpty);
|
3319
3264
|
|
3320
|
-
|
3321
|
-
|
3322
|
-
|
3323
|
-
|
3324
|
-
|
3325
|
-
|
3326
|
-
)
|
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
|
+
}
|
3327
3280
|
}
|
3328
3281
|
|
3329
|
-
const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
|
3330
3282
|
|
3331
3283
|
// store length
|
3332
3284
|
out.push(
|
3333
|
-
...
|
3285
|
+
...pointer,
|
3334
3286
|
...number(length, Valtype.i32),
|
3335
3287
|
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
|
3336
3288
|
);
|
@@ -3342,11 +3294,11 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3342
3294
|
|
3343
3295
|
const offset = ValtypeSize.i32 + i * sizePerEl;
|
3344
3296
|
out.push(
|
3345
|
-
...
|
3297
|
+
...pointer,
|
3346
3298
|
...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
|
3347
3299
|
[ storeOp, 0, ...unsignedLEB128(offset) ],
|
3348
3300
|
...(!typed ? [] : [ // typed presumes !useRawElements
|
3349
|
-
...
|
3301
|
+
...pointer,
|
3350
3302
|
...getNodeType(scope, elements[i]),
|
3351
3303
|
[ Opcodes.i32_store8, 0, ...unsignedLEB128(offset + ValtypeSize[itemType]) ]
|
3352
3304
|
])
|
@@ -3354,12 +3306,13 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3354
3306
|
}
|
3355
3307
|
|
3356
3308
|
// local value as pointer
|
3357
|
-
out.push(...
|
3309
|
+
out.push(...pointer);
|
3310
|
+
if (!intOut) out.push(Opcodes.i32_from_u);
|
3358
3311
|
|
3359
3312
|
return [ out, pointer ];
|
3360
3313
|
};
|
3361
3314
|
|
3362
|
-
const storeArray = (scope, array, index, element
|
3315
|
+
const storeArray = (scope, array, index, element) => {
|
3363
3316
|
if (!Array.isArray(element)) element = generate(scope, element);
|
3364
3317
|
if (typeof index === 'number') index = number(index);
|
3365
3318
|
|
@@ -3371,26 +3324,25 @@ const storeArray = (scope, array, index, element, aotPointer = null) => {
|
|
3371
3324
|
Opcodes.i32_to_u,
|
3372
3325
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3373
3326
|
[ Opcodes.i32_mul ],
|
3374
|
-
|
3375
|
-
|
3376
|
-
|
3377
|
-
|
3378
|
-
]),
|
3327
|
+
|
3328
|
+
...array,
|
3329
|
+
Opcodes.i32_to_u,
|
3330
|
+
[ Opcodes.i32_add ],
|
3379
3331
|
[ Opcodes.local_set, offset ],
|
3380
3332
|
|
3381
3333
|
// store value
|
3382
3334
|
[ Opcodes.local_get, offset ],
|
3383
3335
|
...generate(scope, element),
|
3384
|
-
[ Opcodes.store, 0,
|
3336
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
3385
3337
|
|
3386
3338
|
// store type
|
3387
3339
|
[ Opcodes.local_get, offset ],
|
3388
3340
|
...getNodeType(scope, element),
|
3389
|
-
[ Opcodes.i32_store8, 0,
|
3341
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3390
3342
|
];
|
3391
3343
|
};
|
3392
3344
|
|
3393
|
-
const loadArray = (scope, array, index
|
3345
|
+
const loadArray = (scope, array, index) => {
|
3394
3346
|
if (typeof index === 'number') index = number(index);
|
3395
3347
|
|
3396
3348
|
const offset = localTmp(scope, '#loadArray_offset', Valtype.i32);
|
@@ -3401,20 +3353,19 @@ const loadArray = (scope, array, index, aotPointer = null) => {
|
|
3401
3353
|
Opcodes.i32_to_u,
|
3402
3354
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3403
3355
|
[ Opcodes.i32_mul ],
|
3404
|
-
|
3405
|
-
|
3406
|
-
|
3407
|
-
|
3408
|
-
]),
|
3356
|
+
|
3357
|
+
...array,
|
3358
|
+
Opcodes.i32_to_u,
|
3359
|
+
[ Opcodes.i32_add ],
|
3409
3360
|
[ Opcodes.local_set, offset ],
|
3410
3361
|
|
3411
3362
|
// load value
|
3412
3363
|
[ Opcodes.local_get, offset ],
|
3413
|
-
[ Opcodes.load, 0,
|
3364
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
3414
3365
|
|
3415
3366
|
// load type
|
3416
3367
|
[ Opcodes.local_get, offset ],
|
3417
|
-
[ Opcodes.i32_load8_u, 0,
|
3368
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3418
3369
|
];
|
3419
3370
|
};
|
3420
3371
|
|
@@ -3446,7 +3397,7 @@ const makeString = (scope, str, global = false, name = '$undeclared', forceBytes
|
|
3446
3397
|
};
|
3447
3398
|
|
3448
3399
|
const generateArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false) => {
|
3449
|
-
return makeArray(scope, decl, global, name, initEmpty, valtype, true)[0];
|
3400
|
+
return makeArray(scope, decl, global, name, initEmpty, valtype, false, true)[0];
|
3450
3401
|
};
|
3451
3402
|
|
3452
3403
|
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
@@ -3465,9 +3416,6 @@ const withType = (scope, wasm, type) => [
|
|
3465
3416
|
|
3466
3417
|
const generateMember = (scope, decl, _global, _name) => {
|
3467
3418
|
const name = decl.object.name;
|
3468
|
-
const pointer = scope.arrays?.get(name);
|
3469
|
-
|
3470
|
-
const aotPointer = Prefs.aotPointerOpt && pointer;
|
3471
3419
|
|
3472
3420
|
// hack: .name
|
3473
3421
|
if (decl.property.name === 'name') {
|
@@ -3508,12 +3456,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3508
3456
|
if (Prefs.fastLength) {
|
3509
3457
|
// presume valid length object
|
3510
3458
|
return [
|
3511
|
-
...(
|
3512
|
-
|
3513
|
-
Opcodes.i32_to_u
|
3514
|
-
]),
|
3459
|
+
...generate(scope, decl.object),
|
3460
|
+
Opcodes.i32_to_u,
|
3515
3461
|
|
3516
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3462
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3517
3463
|
Opcodes.i32_from_u
|
3518
3464
|
];
|
3519
3465
|
}
|
@@ -3522,12 +3468,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3522
3468
|
const known = knownType(scope, type);
|
3523
3469
|
if (known != null) {
|
3524
3470
|
if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(known)) return [
|
3525
|
-
...(
|
3526
|
-
|
3527
|
-
Opcodes.i32_to_u
|
3528
|
-
]),
|
3471
|
+
...generate(scope, decl.object),
|
3472
|
+
Opcodes.i32_to_u,
|
3529
3473
|
|
3530
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3474
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3531
3475
|
Opcodes.i32_from_u
|
3532
3476
|
];
|
3533
3477
|
|
@@ -3537,12 +3481,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3537
3481
|
return [
|
3538
3482
|
...typeIsOneOf(getNodeType(scope, decl.object), [ TYPES.string, TYPES.bytestring, TYPES.array ]),
|
3539
3483
|
[ Opcodes.if, valtypeBinary ],
|
3540
|
-
...(
|
3541
|
-
|
3542
|
-
Opcodes.i32_to_u
|
3543
|
-
]),
|
3484
|
+
...generate(scope, decl.object),
|
3485
|
+
Opcodes.i32_to_u,
|
3544
3486
|
|
3545
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3487
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3546
3488
|
Opcodes.i32_from_u,
|
3547
3489
|
|
3548
3490
|
...setLastType(scope, TYPES.number),
|
@@ -3585,25 +3527,29 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3585
3527
|
|
3586
3528
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3587
3529
|
// hack: this is naughty and will break things!
|
3588
|
-
let newOut = number(0,
|
3530
|
+
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3589
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?
|
3590
3533
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3591
|
-
rawElements: new Array(
|
3592
|
-
}, _global, _name, true, 'i16');
|
3534
|
+
rawElements: new Array(0)
|
3535
|
+
}, _global, _name, true, 'i16', true);
|
3593
3536
|
}
|
3594
3537
|
|
3595
3538
|
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3596
3539
|
[TYPES.array]: [
|
3597
|
-
...loadArray(scope, object, property
|
3540
|
+
...loadArray(scope, object, property),
|
3598
3541
|
...setLastType(scope)
|
3599
3542
|
],
|
3600
|
-
|
3601
3543
|
[TYPES.string]: [
|
3602
3544
|
// setup new/out array
|
3603
3545
|
...newOut,
|
3604
|
-
[ Opcodes.drop ],
|
3605
3546
|
|
3606
|
-
|
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,
|
3607
3553
|
|
3608
3554
|
...property,
|
3609
3555
|
Opcodes.i32_to_u,
|
@@ -3611,46 +3557,48 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3611
3557
|
...number(ValtypeSize.i16, Valtype.i32),
|
3612
3558
|
[ Opcodes.i32_mul ],
|
3613
3559
|
|
3614
|
-
...
|
3615
|
-
|
3616
|
-
|
3617
|
-
[ Opcodes.i32_add ]
|
3618
|
-
]),
|
3560
|
+
...object,
|
3561
|
+
Opcodes.i32_to_u,
|
3562
|
+
[ Opcodes.i32_add ],
|
3619
3563
|
|
3620
3564
|
// load current string ind {arg}
|
3621
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
3565
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3622
3566
|
|
3623
3567
|
// store to new string ind 0
|
3624
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
3568
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3625
3569
|
|
3626
3570
|
// return new string (page)
|
3627
|
-
...
|
3571
|
+
...newPointer,
|
3572
|
+
Opcodes.i32_from_u,
|
3628
3573
|
...setLastType(scope, TYPES.string)
|
3629
3574
|
],
|
3630
3575
|
[TYPES.bytestring]: [
|
3631
3576
|
// setup new/out array
|
3632
3577
|
...newOut,
|
3633
|
-
[ Opcodes.drop ],
|
3634
3578
|
|
3635
|
-
|
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,
|
3636
3585
|
|
3637
3586
|
...property,
|
3638
3587
|
Opcodes.i32_to_u,
|
3639
3588
|
|
3640
|
-
...
|
3641
|
-
|
3642
|
-
|
3643
|
-
[ Opcodes.i32_add ]
|
3644
|
-
]),
|
3589
|
+
...object,
|
3590
|
+
Opcodes.i32_to_u,
|
3591
|
+
[ Opcodes.i32_add ],
|
3645
3592
|
|
3646
3593
|
// load current string ind {arg}
|
3647
|
-
[ Opcodes.i32_load8_u, 0,
|
3594
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
3648
3595
|
|
3649
3596
|
// store to new string ind 0
|
3650
|
-
[ Opcodes.i32_store8, 0,
|
3597
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
3651
3598
|
|
3652
3599
|
// return new string (page)
|
3653
|
-
...
|
3600
|
+
...newPointer,
|
3601
|
+
Opcodes.i32_from_u,
|
3654
3602
|
...setLastType(scope, TYPES.bytestring)
|
3655
3603
|
],
|
3656
3604
|
|
@@ -3658,7 +3606,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3658
3606
|
});
|
3659
3607
|
};
|
3660
3608
|
|
3661
|
-
const randId = () => Math.random().toString(16).slice(
|
3609
|
+
const randId = () => Math.random().toString(16).slice(1, -2).padEnd(12, '0');
|
3662
3610
|
|
3663
3611
|
const objectHack = node => {
|
3664
3612
|
if (!node) return node;
|
@@ -3710,7 +3658,7 @@ const generateFunc = (scope, decl) => {
|
|
3710
3658
|
if (decl.async) return todo(scope, 'async functions are not supported');
|
3711
3659
|
if (decl.generator) return todo(scope, 'generator functions are not supported');
|
3712
3660
|
|
3713
|
-
const name = decl.id ? decl.id.name : `
|
3661
|
+
const name = decl.id ? decl.id.name : `anonymous${randId()}`;
|
3714
3662
|
const params = decl.params ?? [];
|
3715
3663
|
|
3716
3664
|
// TODO: share scope/locals between !!!
|
@@ -3795,9 +3743,9 @@ const internalConstrs = {
|
|
3795
3743
|
|
3796
3744
|
// new Array(n)
|
3797
3745
|
|
3798
|
-
const [ , pointer ] = makeArray(scope, {
|
3746
|
+
const [ out, pointer ] = makeArray(scope, {
|
3799
3747
|
rawElements: new Array(0)
|
3800
|
-
}, global, name, true);
|
3748
|
+
}, global, name, true, undefined, true);
|
3801
3749
|
|
3802
3750
|
const arg = decl.arguments[0] ?? DEFAULT_VALUE;
|
3803
3751
|
|
@@ -3806,12 +3754,13 @@ const internalConstrs = {
|
|
3806
3754
|
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeThrow', 'Invalid array length', true);
|
3807
3755
|
|
3808
3756
|
return [
|
3809
|
-
...
|
3757
|
+
...out,
|
3810
3758
|
...generate(scope, arg, global, name),
|
3811
3759
|
Opcodes.i32_to_u,
|
3812
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
3760
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3813
3761
|
|
3814
|
-
...
|
3762
|
+
...pointer,
|
3763
|
+
Opcodes.i32_from_u
|
3815
3764
|
];
|
3816
3765
|
},
|
3817
3766
|
type: TYPES.array,
|
@@ -3960,8 +3909,9 @@ const internalConstrs = {
|
|
3960
3909
|
};
|
3961
3910
|
|
3962
3911
|
export default program => {
|
3963
|
-
globals = {
|
3964
|
-
|
3912
|
+
globals = {
|
3913
|
+
['#ind']: 0
|
3914
|
+
};
|
3965
3915
|
tags = [];
|
3966
3916
|
exceptions = [];
|
3967
3917
|
funcs = [];
|
@@ -3994,6 +3944,7 @@ export default program => {
|
|
3994
3944
|
builtinFuncs = new BuiltinFuncs();
|
3995
3945
|
builtinVars = new BuiltinVars();
|
3996
3946
|
prototypeFuncs = new PrototypeFuncs();
|
3947
|
+
allocator = makeAllocator(Prefs.allocator ?? 'static');
|
3997
3948
|
|
3998
3949
|
program.id = { name: 'main' };
|
3999
3950
|
|
@@ -4036,6 +3987,8 @@ export default program => {
|
|
4036
3987
|
else main.returns = [];
|
4037
3988
|
}
|
4038
3989
|
|
3990
|
+
delete globals['#ind'];
|
3991
|
+
|
4039
3992
|
// if blank main func and other exports, remove it
|
4040
3993
|
if (main.wasm.length === 0 && funcs.reduce((acc, x) => acc + (x.export ? 1 : 0), 0) > 1) funcs.splice(main.index - importedFuncs.length, 1);
|
4041
3994
|
|