porffor 0.16.0-79cd8c0c8 → 0.16.0-8107e135a
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/bf +0 -0
- package/compiler/allocators/grow.js +25 -0
- package/compiler/allocators/index.js +10 -0
- package/compiler/allocators/static.js +42 -0
- package/compiler/assemble.js +7 -1
- package/compiler/builtins/date.ts +2 -4
- package/compiler/builtins/set.ts +2 -4
- package/compiler/codegen.js +225 -291
- package/compiler/cyclone.js +11 -11
- package/compiler/generated_builtins.js +46 -46
- package/compiler/opt.js +7 -5
- package/compiler/parse.js +1 -1
- package/compiler/precompile.js +12 -7
- package/compiler/prefs.js +1 -1
- package/compiler/prototype.js +34 -43
- package/compiler/wasmSpec.js +2 -2
- package/compiler/wrap.js +2 -1
- package/package.json +2 -4
- package/runner/index.js +8 -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 Allocator from './allocators/index.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) {
|
@@ -181,12 +182,6 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
181
182
|
continue;
|
182
183
|
}
|
183
184
|
|
184
|
-
if (asm[0] === 'memory') {
|
185
|
-
allocPage(scope, 'asm instrinsic');
|
186
|
-
// todo: add to store/load offset insts
|
187
|
-
continue;
|
188
|
-
}
|
189
|
-
|
190
185
|
let inst = Opcodes[asm[0].replace('.', '_')];
|
191
186
|
if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
192
187
|
|
@@ -433,63 +428,12 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
433
428
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
434
429
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
435
430
|
|
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
431
|
const leftPointer = localTmp(scope, 'concat_left_pointer', Valtype.i32);
|
488
432
|
|
489
433
|
// alloc/assign array
|
490
|
-
const [ , pointer ] = makeArray(scope, {
|
434
|
+
const [ out, pointer ] = makeArray(scope, {
|
491
435
|
rawElements: new Array(0)
|
492
|
-
}, global, name, true, 'i16');
|
436
|
+
}, global, name, true, 'i16', true);
|
493
437
|
|
494
438
|
return [
|
495
439
|
// setup left
|
@@ -503,7 +447,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
503
447
|
[ Opcodes.local_set, rightPointer ],
|
504
448
|
|
505
449
|
// calculate length
|
506
|
-
...
|
450
|
+
...out,
|
507
451
|
|
508
452
|
[ Opcodes.local_get, leftPointer ],
|
509
453
|
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
@@ -516,11 +460,13 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
516
460
|
[ Opcodes.i32_add ],
|
517
461
|
|
518
462
|
// store length
|
519
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
463
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
520
464
|
|
521
465
|
// copy left
|
522
466
|
// dst = out pointer + length size
|
523
|
-
...
|
467
|
+
...pointer,
|
468
|
+
...number(ValtypeSize.i32, Valtype.i32),
|
469
|
+
[ Opcodes.i32_add ],
|
524
470
|
|
525
471
|
// src = left pointer + length size
|
526
472
|
[ Opcodes.local_get, leftPointer ],
|
@@ -533,7 +479,9 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
533
479
|
|
534
480
|
// copy right
|
535
481
|
// dst = out pointer + length size + left length * sizeof valtype
|
536
|
-
...
|
482
|
+
...pointer,
|
483
|
+
...number(ValtypeSize.i32, Valtype.i32),
|
484
|
+
[ Opcodes.i32_add ],
|
537
485
|
|
538
486
|
[ Opcodes.local_get, leftLength ],
|
539
487
|
...number(bytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
@@ -553,7 +501,8 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
553
501
|
[ ...Opcodes.memory_copy, 0x00, 0x00 ],
|
554
502
|
|
555
503
|
// return new string (page)
|
556
|
-
...
|
504
|
+
...pointer,
|
505
|
+
Opcodes.i32_from_u
|
557
506
|
];
|
558
507
|
};
|
559
508
|
|
@@ -669,10 +618,10 @@ const compareStrings = (scope, left, right, bytestrings = false) => {
|
|
669
618
|
};
|
670
619
|
|
671
620
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
672
|
-
if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
673
|
-
|
674
|
-
|
675
|
-
];
|
621
|
+
// if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
622
|
+
// ...wasm,
|
623
|
+
// ...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
|
624
|
+
// ];
|
676
625
|
// if (isIntOp(wasm[wasm.length - 1])) return [ ...wasm ];
|
677
626
|
|
678
627
|
// todo/perf: use knownType and custom bytecode here instead of typeSwitch
|
@@ -1068,7 +1017,7 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1068
1017
|
|
1069
1018
|
for (const x of _data) {
|
1070
1019
|
const copy = { ...x };
|
1071
|
-
copy.offset += pages.size * pageSize;
|
1020
|
+
if (copy.offset != null) copy.offset += pages.size * pageSize;
|
1072
1021
|
data.push(copy);
|
1073
1022
|
}
|
1074
1023
|
|
@@ -1091,9 +1040,9 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1091
1040
|
|
1092
1041
|
let baseGlobalIdx, i = 0;
|
1093
1042
|
for (const type of globalTypes) {
|
1094
|
-
if (baseGlobalIdx === undefined) baseGlobalIdx =
|
1043
|
+
if (baseGlobalIdx === undefined) baseGlobalIdx = globals['#ind'];
|
1095
1044
|
|
1096
|
-
globals[globalNames[i] ?? `${name}_global_${i}`] = { idx:
|
1045
|
+
globals[globalNames[i] ?? `${name}_global_${i}`] = { idx: globals['#ind']++, type, init: globalInits[i] ?? 0 };
|
1097
1046
|
i++;
|
1098
1047
|
}
|
1099
1048
|
|
@@ -1106,11 +1055,15 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1106
1055
|
}
|
1107
1056
|
}
|
1108
1057
|
|
1109
|
-
if (table)
|
1110
|
-
|
1111
|
-
inst.
|
1112
|
-
|
1058
|
+
if (table) {
|
1059
|
+
for (const inst of wasm) {
|
1060
|
+
if (inst[0] === Opcodes.i32_load16_u && inst.at(-1) === 'read_argc') {
|
1061
|
+
inst.splice(2, 99);
|
1062
|
+
inst.push(...unsignedLEB128(allocPage({}, 'func argc lut') * pageSize));
|
1063
|
+
}
|
1113
1064
|
}
|
1065
|
+
|
1066
|
+
funcs.table = true;
|
1114
1067
|
}
|
1115
1068
|
|
1116
1069
|
func.wasm = wasm;
|
@@ -1450,10 +1403,10 @@ const countLeftover = wasm => {
|
|
1450
1403
|
|
1451
1404
|
if (depth === 0)
|
1452
1405
|
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] <
|
1406
|
+
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
1407
|
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
1408
|
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]
|
1409
|
+
else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
|
1457
1410
|
else if (inst[0] === Opcodes.return) count = 0;
|
1458
1411
|
else if (inst[0] === Opcodes.call) {
|
1459
1412
|
let func = funcs.find(x => x.index === inst[1]);
|
@@ -1725,7 +1678,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1725
1678
|
}, generate(scope, decl.arguments[0] ?? DEFAULT_VALUE), getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE), protoLocal, protoLocal2, (length, itemType) => {
|
1726
1679
|
return makeArray(scope, {
|
1727
1680
|
rawElements: new Array(length)
|
1728
|
-
}, _global, _name, true, itemType);
|
1681
|
+
}, _global, _name, true, itemType, true);
|
1729
1682
|
}, () => {
|
1730
1683
|
optUnused = true;
|
1731
1684
|
return unusedValue;
|
@@ -2115,7 +2068,6 @@ const brTable = (input, bc, returns) => {
|
|
2115
2068
|
}
|
2116
2069
|
|
2117
2070
|
for (let i = 0; i < count; i++) {
|
2118
|
-
// if (i === 0) out.push([ Opcodes.block, returns, 'br table start' ]);
|
2119
2071
|
if (i === 0) out.push([ Opcodes.block, returns ]);
|
2120
2072
|
else out.push([ Opcodes.block, Blocktype.void ]);
|
2121
2073
|
}
|
@@ -2149,10 +2101,8 @@ const brTable = (input, bc, returns) => {
|
|
2149
2101
|
[ Opcodes.br_table, ...encodeVector(table), 0 ]
|
2150
2102
|
);
|
2151
2103
|
|
2152
|
-
//
|
2153
|
-
// (
|
2154
|
-
// dm me and if you are correct and the first person
|
2155
|
-
// I will somehow shout you out or something
|
2104
|
+
// sort the wrong way and then reverse
|
2105
|
+
// so strings ('default') are at the start before any numbers
|
2156
2106
|
const orderedBc = keys.sort((a, b) => b - a).reverse();
|
2157
2107
|
|
2158
2108
|
br = count - 1;
|
@@ -2178,7 +2128,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
|
2178
2128
|
return bc[known] ?? bc.default;
|
2179
2129
|
}
|
2180
2130
|
|
2181
|
-
if (Prefs.
|
2131
|
+
if (Prefs.typeswitchBrtable)
|
2182
2132
|
return brTable(type, bc, returns);
|
2183
2133
|
|
2184
2134
|
const tmp = localTmp(scope, '#typeswitch_tmp' + (Prefs.typeswitchUniqueTmp ? randId() : ''), Valtype.i32);
|
@@ -2233,11 +2183,11 @@ const allocVar = (scope, name, global = false, type = true) => {
|
|
2233
2183
|
return target[name].idx;
|
2234
2184
|
}
|
2235
2185
|
|
2236
|
-
let idx = global ?
|
2186
|
+
let idx = global ? globals['#ind']++ : scope.localInd++;
|
2237
2187
|
target[name] = { idx, type: valtypeBinary };
|
2238
2188
|
|
2239
2189
|
if (type) {
|
2240
|
-
let typeIdx = global ?
|
2190
|
+
let typeIdx = global ? globals['#ind']++ : scope.localInd++;
|
2241
2191
|
target[name + '#type'] = { idx: typeIdx, type: Valtype.i32, name };
|
2242
2192
|
}
|
2243
2193
|
|
@@ -2330,24 +2280,10 @@ const generateVar = (scope, decl) => {
|
|
2330
2280
|
}
|
2331
2281
|
|
2332
2282
|
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
|
-
// }
|
2283
|
+
const alreadyArray = scope.arrays?.get(name) != null;
|
2348
2284
|
|
2349
2285
|
const generated = generate(scope, x.init, global, name);
|
2350
|
-
if (scope.arrays?.get(name) != null) {
|
2286
|
+
if (!alreadyArray && scope.arrays?.get(name) != null) {
|
2351
2287
|
// hack to set local as pointer before
|
2352
2288
|
out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2353
2289
|
if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
|
@@ -2399,19 +2335,12 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2399
2335
|
|
2400
2336
|
// hack: .length setter
|
2401
2337
|
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
2338
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2408
2339
|
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2409
2340
|
|
2410
2341
|
return [
|
2411
|
-
...(
|
2412
|
-
|
2413
|
-
Opcodes.i32_to_u
|
2414
|
-
]),
|
2342
|
+
...generate(scope, decl.left.object),
|
2343
|
+
Opcodes.i32_to_u,
|
2415
2344
|
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2416
2345
|
|
2417
2346
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
@@ -2422,7 +2351,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2422
2351
|
[ Opcodes.local_tee, newValueTmp ],
|
2423
2352
|
|
2424
2353
|
Opcodes.i32_to_u,
|
2425
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
2354
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2426
2355
|
|
2427
2356
|
[ Opcodes.local_get, newValueTmp ]
|
2428
2357
|
];
|
@@ -2430,21 +2359,14 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2430
2359
|
|
2431
2360
|
// arr[i]
|
2432
2361
|
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
2362
|
const newValueTmp = localTmp(scope, '__member_setter_val_tmp');
|
2439
2363
|
const pointerTmp = op === '=' ? -1 : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2440
2364
|
|
2441
2365
|
return [
|
2442
2366
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2443
2367
|
[TYPES.array]: [
|
2444
|
-
...(
|
2445
|
-
|
2446
|
-
Opcodes.i32_to_u
|
2447
|
-
]),
|
2368
|
+
...generate(scope, decl.left.object),
|
2369
|
+
Opcodes.i32_to_u,
|
2448
2370
|
|
2449
2371
|
// get index as valtype
|
2450
2372
|
...generate(scope, decl.left.property),
|
@@ -2453,39 +2375,22 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2453
2375
|
// turn into byte offset by * valtypeSize (4 for i32, 8 for i64/f64)
|
2454
2376
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
2455
2377
|
[ Opcodes.i32_mul ],
|
2456
|
-
|
2378
|
+
[ Opcodes.i32_add ],
|
2457
2379
|
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2458
2380
|
|
2459
2381
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2460
2382
|
[ Opcodes.local_get, pointerTmp ],
|
2461
|
-
[ Opcodes.load, 0,
|
2383
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ]
|
2462
2384
|
], generate(scope, decl.right), [
|
2463
2385
|
[ Opcodes.local_get, pointerTmp ],
|
2464
|
-
[ Opcodes.i32_load8_u, 0,
|
2386
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2465
2387
|
], getNodeType(scope, decl.right), false, name, true)),
|
2466
2388
|
[ Opcodes.local_tee, newValueTmp ],
|
2467
2389
|
|
2468
|
-
[ Opcodes.store, 0,
|
2390
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2469
2391
|
],
|
2470
2392
|
|
2471
2393
|
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
2394
|
}, Blocktype.void),
|
2490
2395
|
|
2491
2396
|
[ Opcodes.local_get, newValueTmp ]
|
@@ -2869,12 +2774,12 @@ const generateForOf = (scope, decl) => {
|
|
2869
2774
|
|
2870
2775
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2871
2776
|
// hack: this is naughty and will break things!
|
2872
|
-
let newOut = number(0, Valtype.
|
2777
|
+
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
2873
2778
|
if (pages.hasAnyString) {
|
2874
2779
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2875
2780
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2876
|
-
rawElements: new Array(
|
2877
|
-
}, isGlobal, leftName, true, 'i16');
|
2781
|
+
rawElements: new Array(0)
|
2782
|
+
}, isGlobal, leftName, true, 'i16', true);
|
2878
2783
|
}
|
2879
2784
|
|
2880
2785
|
// set type for local
|
@@ -2921,23 +2826,28 @@ const generateForOf = (scope, decl) => {
|
|
2921
2826
|
[TYPES.string]: [
|
2922
2827
|
...setType(scope, leftName, TYPES.string),
|
2923
2828
|
|
2924
|
-
[ Opcodes.loop, Blocktype.void ],
|
2925
|
-
|
2926
2829
|
// setup new/out array
|
2927
2830
|
...newOut,
|
2928
|
-
[ Opcodes.drop ],
|
2929
2831
|
|
2930
|
-
|
2832
|
+
// set length to 1
|
2833
|
+
...number(1, Valtype.i32),
|
2834
|
+
[ Opcodes.i32_store, 0, 0 ],
|
2835
|
+
|
2836
|
+
[ Opcodes.loop, Blocktype.void ],
|
2837
|
+
|
2838
|
+
// use as pointer for store later
|
2839
|
+
...newPointer,
|
2931
2840
|
|
2932
2841
|
// load current string ind {arg}
|
2933
2842
|
[ Opcodes.local_get, pointer ],
|
2934
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
2843
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2935
2844
|
|
2936
2845
|
// store to new string ind 0
|
2937
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
2846
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2938
2847
|
|
2939
2848
|
// return new string (page)
|
2940
|
-
...
|
2849
|
+
...newPointer,
|
2850
|
+
Opcodes.i32_from_u,
|
2941
2851
|
|
2942
2852
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2943
2853
|
|
@@ -2969,25 +2879,30 @@ const generateForOf = (scope, decl) => {
|
|
2969
2879
|
[TYPES.bytestring]: [
|
2970
2880
|
...setType(scope, leftName, TYPES.bytestring),
|
2971
2881
|
|
2972
|
-
[ Opcodes.loop, Blocktype.void ],
|
2973
|
-
|
2974
2882
|
// setup new/out array
|
2975
2883
|
...newOut,
|
2976
|
-
[ Opcodes.drop ],
|
2977
2884
|
|
2978
|
-
|
2885
|
+
// set length to 1
|
2886
|
+
...number(1, Valtype.i32),
|
2887
|
+
[ Opcodes.i32_store, 0, 0 ],
|
2888
|
+
|
2889
|
+
[ Opcodes.loop, Blocktype.void ],
|
2890
|
+
|
2891
|
+
// use as pointer for store later
|
2892
|
+
...newPointer,
|
2979
2893
|
|
2980
2894
|
// load current string ind {arg}
|
2981
2895
|
[ Opcodes.local_get, pointer ],
|
2982
2896
|
[ Opcodes.local_get, counter ],
|
2983
2897
|
[ Opcodes.i32_add ],
|
2984
|
-
[ Opcodes.i32_load8_u, 0,
|
2898
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
2985
2899
|
|
2986
2900
|
// store to new string ind 0
|
2987
|
-
[ Opcodes.i32_store8, 0,
|
2901
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
2988
2902
|
|
2989
2903
|
// return new string (page)
|
2990
|
-
...
|
2904
|
+
...newPointer,
|
2905
|
+
Opcodes.i32_from_u,
|
2991
2906
|
|
2992
2907
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2993
2908
|
|
@@ -3207,16 +3122,6 @@ const allocPage = (scope, reason, type) => {
|
|
3207
3122
|
return ind;
|
3208
3123
|
};
|
3209
3124
|
|
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
|
-
return ind;
|
3218
|
-
};
|
3219
|
-
|
3220
3125
|
const itemTypeToValtype = {
|
3221
3126
|
i32: 'i32',
|
3222
3127
|
i64: 'i64',
|
@@ -3251,39 +3156,43 @@ const compileBytes = (val, itemType) => {
|
|
3251
3156
|
}
|
3252
3157
|
};
|
3253
3158
|
|
3254
|
-
const
|
3255
|
-
|
3256
|
-
case 'i8': return 'bytestring';
|
3257
|
-
case 'i16': return 'string';
|
3159
|
+
const makeData = (scope, elements, offset = null, itemType, initEmpty) => {
|
3160
|
+
const length = elements.length;
|
3258
3161
|
|
3259
|
-
|
3260
|
-
|
3261
|
-
};
|
3162
|
+
// if length is 0 memory/data will just be 0000... anyway
|
3163
|
+
if (length === 0) return false;
|
3262
3164
|
|
3263
|
-
|
3264
|
-
|
3165
|
+
let bytes = compileBytes(length, 'i32');
|
3166
|
+
|
3167
|
+
if (!initEmpty) for (let i = 0; i < length; i++) {
|
3168
|
+
if (elements[i] == null) continue;
|
3265
3169
|
|
3266
|
-
|
3170
|
+
bytes.push(...compileBytes(elements[i], itemType));
|
3171
|
+
}
|
3172
|
+
|
3173
|
+
const obj = { bytes };
|
3174
|
+
if (offset != null) obj.offset = offset;
|
3267
3175
|
|
3268
|
-
|
3269
|
-
if (!scope.arrays.has(name) || name === '$undeclared') {
|
3270
|
-
firstAssign = true;
|
3176
|
+
const idx = data.push(obj) - 1;
|
3271
3177
|
|
3272
|
-
|
3273
|
-
|
3178
|
+
scope.data ??= [];
|
3179
|
+
scope.data.push(idx);
|
3274
3180
|
|
3275
|
-
|
3276
|
-
|
3277
|
-
else page = allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType);
|
3181
|
+
return { idx, size: bytes.length };
|
3182
|
+
};
|
3278
3183
|
|
3279
|
-
|
3280
|
-
|
3281
|
-
|
3184
|
+
const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false, itemType = valtype, intOut = false, typed = false) => {
|
3185
|
+
if (itemType !== 'i16' && itemType !== 'i8') {
|
3186
|
+
pages.hasArray = true;
|
3187
|
+
} else {
|
3188
|
+
pages.hasAnyString = true;
|
3189
|
+
if (itemType === 'i8') pages.hasByteString = true;
|
3190
|
+
else pages.hasString = true;
|
3282
3191
|
}
|
3283
3192
|
|
3284
|
-
const
|
3193
|
+
const out = [];
|
3285
3194
|
|
3286
|
-
const
|
3195
|
+
const uniqueName = name === '$undeclared' ? name + randId() : name;
|
3287
3196
|
|
3288
3197
|
const useRawElements = !!decl.rawElements;
|
3289
3198
|
const elements = useRawElements ? decl.rawElements : decl.elements;
|
@@ -3291,46 +3200,70 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3291
3200
|
const valtype = itemTypeToValtype[itemType];
|
3292
3201
|
const length = elements.length;
|
3293
3202
|
|
3294
|
-
|
3295
|
-
// if length is 0 memory/data will just be 0000... anyway
|
3296
|
-
if (length !== 0) {
|
3297
|
-
let bytes = compileBytes(length, 'i32');
|
3203
|
+
const allocated = allocator.alloc({ scope, pages, globals }, uniqueName, { itemType });
|
3298
3204
|
|
3299
|
-
|
3300
|
-
|
3205
|
+
let pointer = allocated;
|
3206
|
+
if (allocator.constructor.name !== 'StaticAllocator') {
|
3207
|
+
// const tmp = localTmp(scope, '#makearray_pointer' + uniqueName, Valtype.i32);
|
3208
|
+
const tmp = localTmp(scope, '#makearray_pointer' + name, Valtype.i32);
|
3209
|
+
out.push(
|
3210
|
+
...allocated,
|
3211
|
+
[ Opcodes.local_set, tmp ]
|
3212
|
+
);
|
3213
|
+
|
3214
|
+
pointer = [ [ Opcodes.local_get, tmp ] ];
|
3301
3215
|
|
3302
|
-
|
3216
|
+
if (Prefs.data && useRawElements) {
|
3217
|
+
const data = makeData(scope, elements, null, itemType, initEmpty);
|
3218
|
+
if (data) {
|
3219
|
+
// init data
|
3220
|
+
out.push(
|
3221
|
+
...pointer,
|
3222
|
+
...number(0, Valtype.i32),
|
3223
|
+
...number(data.size, Valtype.i32),
|
3224
|
+
[ ...Opcodes.memory_init, ...unsignedLEB128(data.idx), 0 ]
|
3225
|
+
);
|
3303
3226
|
}
|
3304
3227
|
|
3305
|
-
|
3306
|
-
|
3307
|
-
|
3308
|
-
|
3228
|
+
// return pointer in out
|
3229
|
+
out.push(
|
3230
|
+
...pointer,
|
3231
|
+
...(!intOut ? [ Opcodes.i32_from_u ] : [])
|
3232
|
+
);
|
3309
3233
|
|
3310
|
-
|
3311
|
-
scope.data.push(ind);
|
3234
|
+
return [ out, pointer ];
|
3312
3235
|
}
|
3236
|
+
} else {
|
3237
|
+
const rawPtr = read_signedLEB128(pointer[0].slice(1));
|
3313
3238
|
|
3314
|
-
|
3315
|
-
|
3239
|
+
scope.arrays ??= new Map();
|
3240
|
+
const firstAssign = !scope.arrays.has(uniqueName);
|
3241
|
+
if (firstAssign) scope.arrays.set(uniqueName, rawPtr);
|
3316
3242
|
|
3317
|
-
|
3318
|
-
|
3243
|
+
if (Prefs.data && firstAssign && useRawElements) {
|
3244
|
+
makeData(scope, elements, rawPtr, itemType, initEmpty);
|
3319
3245
|
|
3320
|
-
|
3321
|
-
|
3322
|
-
|
3323
|
-
|
3324
|
-
|
3325
|
-
|
3326
|
-
)
|
3246
|
+
// local value as pointer
|
3247
|
+
return [ number(rawPtr, intOut ? Valtype.i32 : valtypeBinary), pointer ];
|
3248
|
+
}
|
3249
|
+
|
3250
|
+
const local = global ? globals[name] : scope.locals[name];
|
3251
|
+
const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
|
3252
|
+
if (pointerTmp != null) {
|
3253
|
+
out.push(
|
3254
|
+
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
3255
|
+
Opcodes.i32_to_u,
|
3256
|
+
[ Opcodes.local_set, pointerTmp ]
|
3257
|
+
);
|
3258
|
+
|
3259
|
+
pointer = [ [ Opcodes.local_get, pointerTmp ] ];
|
3260
|
+
}
|
3327
3261
|
}
|
3328
3262
|
|
3329
|
-
const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
|
3330
3263
|
|
3331
3264
|
// store length
|
3332
3265
|
out.push(
|
3333
|
-
...
|
3266
|
+
...pointer,
|
3334
3267
|
...number(length, Valtype.i32),
|
3335
3268
|
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
|
3336
3269
|
);
|
@@ -3342,11 +3275,11 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3342
3275
|
|
3343
3276
|
const offset = ValtypeSize.i32 + i * sizePerEl;
|
3344
3277
|
out.push(
|
3345
|
-
...
|
3278
|
+
...pointer,
|
3346
3279
|
...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
|
3347
3280
|
[ storeOp, 0, ...unsignedLEB128(offset) ],
|
3348
3281
|
...(!typed ? [] : [ // typed presumes !useRawElements
|
3349
|
-
...
|
3282
|
+
...pointer,
|
3350
3283
|
...getNodeType(scope, elements[i]),
|
3351
3284
|
[ Opcodes.i32_store8, 0, ...unsignedLEB128(offset + ValtypeSize[itemType]) ]
|
3352
3285
|
])
|
@@ -3354,12 +3287,13 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3354
3287
|
}
|
3355
3288
|
|
3356
3289
|
// local value as pointer
|
3357
|
-
out.push(...
|
3290
|
+
out.push(...pointer);
|
3291
|
+
if (!intOut) out.push(Opcodes.i32_from_u);
|
3358
3292
|
|
3359
3293
|
return [ out, pointer ];
|
3360
3294
|
};
|
3361
3295
|
|
3362
|
-
const storeArray = (scope, array, index, element
|
3296
|
+
const storeArray = (scope, array, index, element) => {
|
3363
3297
|
if (!Array.isArray(element)) element = generate(scope, element);
|
3364
3298
|
if (typeof index === 'number') index = number(index);
|
3365
3299
|
|
@@ -3371,26 +3305,25 @@ const storeArray = (scope, array, index, element, aotPointer = null) => {
|
|
3371
3305
|
Opcodes.i32_to_u,
|
3372
3306
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3373
3307
|
[ Opcodes.i32_mul ],
|
3374
|
-
|
3375
|
-
|
3376
|
-
|
3377
|
-
|
3378
|
-
]),
|
3308
|
+
|
3309
|
+
...array,
|
3310
|
+
Opcodes.i32_to_u,
|
3311
|
+
[ Opcodes.i32_add ],
|
3379
3312
|
[ Opcodes.local_set, offset ],
|
3380
3313
|
|
3381
3314
|
// store value
|
3382
3315
|
[ Opcodes.local_get, offset ],
|
3383
3316
|
...generate(scope, element),
|
3384
|
-
[ Opcodes.store, 0,
|
3317
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
3385
3318
|
|
3386
3319
|
// store type
|
3387
3320
|
[ Opcodes.local_get, offset ],
|
3388
3321
|
...getNodeType(scope, element),
|
3389
|
-
[ Opcodes.i32_store8, 0,
|
3322
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3390
3323
|
];
|
3391
3324
|
};
|
3392
3325
|
|
3393
|
-
const loadArray = (scope, array, index
|
3326
|
+
const loadArray = (scope, array, index) => {
|
3394
3327
|
if (typeof index === 'number') index = number(index);
|
3395
3328
|
|
3396
3329
|
const offset = localTmp(scope, '#loadArray_offset', Valtype.i32);
|
@@ -3401,20 +3334,19 @@ const loadArray = (scope, array, index, aotPointer = null) => {
|
|
3401
3334
|
Opcodes.i32_to_u,
|
3402
3335
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3403
3336
|
[ Opcodes.i32_mul ],
|
3404
|
-
|
3405
|
-
|
3406
|
-
|
3407
|
-
|
3408
|
-
]),
|
3337
|
+
|
3338
|
+
...array,
|
3339
|
+
Opcodes.i32_to_u,
|
3340
|
+
[ Opcodes.i32_add ],
|
3409
3341
|
[ Opcodes.local_set, offset ],
|
3410
3342
|
|
3411
3343
|
// load value
|
3412
3344
|
[ Opcodes.local_get, offset ],
|
3413
|
-
[ Opcodes.load, 0,
|
3345
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
3414
3346
|
|
3415
3347
|
// load type
|
3416
3348
|
[ Opcodes.local_get, offset ],
|
3417
|
-
[ Opcodes.i32_load8_u, 0,
|
3349
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3418
3350
|
];
|
3419
3351
|
};
|
3420
3352
|
|
@@ -3446,7 +3378,7 @@ const makeString = (scope, str, global = false, name = '$undeclared', forceBytes
|
|
3446
3378
|
};
|
3447
3379
|
|
3448
3380
|
const generateArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false) => {
|
3449
|
-
return makeArray(scope, decl, global, name, initEmpty, valtype, true)[0];
|
3381
|
+
return makeArray(scope, decl, global, name, initEmpty, valtype, false, true)[0];
|
3450
3382
|
};
|
3451
3383
|
|
3452
3384
|
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
@@ -3465,9 +3397,6 @@ const withType = (scope, wasm, type) => [
|
|
3465
3397
|
|
3466
3398
|
const generateMember = (scope, decl, _global, _name) => {
|
3467
3399
|
const name = decl.object.name;
|
3468
|
-
const pointer = scope.arrays?.get(name);
|
3469
|
-
|
3470
|
-
const aotPointer = Prefs.aotPointerOpt && pointer;
|
3471
3400
|
|
3472
3401
|
// hack: .name
|
3473
3402
|
if (decl.property.name === 'name') {
|
@@ -3508,12 +3437,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3508
3437
|
if (Prefs.fastLength) {
|
3509
3438
|
// presume valid length object
|
3510
3439
|
return [
|
3511
|
-
...(
|
3512
|
-
|
3513
|
-
Opcodes.i32_to_u
|
3514
|
-
]),
|
3440
|
+
...generate(scope, decl.object),
|
3441
|
+
Opcodes.i32_to_u,
|
3515
3442
|
|
3516
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3443
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3517
3444
|
Opcodes.i32_from_u
|
3518
3445
|
];
|
3519
3446
|
}
|
@@ -3522,12 +3449,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3522
3449
|
const known = knownType(scope, type);
|
3523
3450
|
if (known != null) {
|
3524
3451
|
if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(known)) return [
|
3525
|
-
...(
|
3526
|
-
|
3527
|
-
Opcodes.i32_to_u
|
3528
|
-
]),
|
3452
|
+
...generate(scope, decl.object),
|
3453
|
+
Opcodes.i32_to_u,
|
3529
3454
|
|
3530
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3455
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3531
3456
|
Opcodes.i32_from_u
|
3532
3457
|
];
|
3533
3458
|
|
@@ -3537,12 +3462,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3537
3462
|
return [
|
3538
3463
|
...typeIsOneOf(getNodeType(scope, decl.object), [ TYPES.string, TYPES.bytestring, TYPES.array ]),
|
3539
3464
|
[ Opcodes.if, valtypeBinary ],
|
3540
|
-
...(
|
3541
|
-
|
3542
|
-
Opcodes.i32_to_u
|
3543
|
-
]),
|
3465
|
+
...generate(scope, decl.object),
|
3466
|
+
Opcodes.i32_to_u,
|
3544
3467
|
|
3545
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3468
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3546
3469
|
Opcodes.i32_from_u,
|
3547
3470
|
|
3548
3471
|
...setLastType(scope, TYPES.number),
|
@@ -3585,25 +3508,29 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3585
3508
|
|
3586
3509
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3587
3510
|
// hack: this is naughty and will break things!
|
3588
|
-
let newOut = number(0,
|
3511
|
+
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3589
3512
|
if (pages.hasAnyString) {
|
3513
|
+
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3590
3514
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3591
|
-
rawElements: new Array(
|
3592
|
-
}, _global, _name, true, 'i16');
|
3515
|
+
rawElements: new Array(0)
|
3516
|
+
}, _global, _name, true, 'i16', true);
|
3593
3517
|
}
|
3594
3518
|
|
3595
3519
|
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3596
3520
|
[TYPES.array]: [
|
3597
|
-
...loadArray(scope, object, property
|
3521
|
+
...loadArray(scope, object, property),
|
3598
3522
|
...setLastType(scope)
|
3599
3523
|
],
|
3600
|
-
|
3601
3524
|
[TYPES.string]: [
|
3602
3525
|
// setup new/out array
|
3603
3526
|
...newOut,
|
3604
|
-
[ Opcodes.drop ],
|
3605
3527
|
|
3606
|
-
|
3528
|
+
// set length to 1
|
3529
|
+
...number(1, Valtype.i32),
|
3530
|
+
[ Opcodes.i32_store, 0, 0 ],
|
3531
|
+
|
3532
|
+
// use as pointer for store later
|
3533
|
+
...newPointer,
|
3607
3534
|
|
3608
3535
|
...property,
|
3609
3536
|
Opcodes.i32_to_u,
|
@@ -3611,46 +3538,48 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3611
3538
|
...number(ValtypeSize.i16, Valtype.i32),
|
3612
3539
|
[ Opcodes.i32_mul ],
|
3613
3540
|
|
3614
|
-
...
|
3615
|
-
|
3616
|
-
|
3617
|
-
[ Opcodes.i32_add ]
|
3618
|
-
]),
|
3541
|
+
...object,
|
3542
|
+
Opcodes.i32_to_u,
|
3543
|
+
[ Opcodes.i32_add ],
|
3619
3544
|
|
3620
3545
|
// load current string ind {arg}
|
3621
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
3546
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3622
3547
|
|
3623
3548
|
// store to new string ind 0
|
3624
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
3549
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3625
3550
|
|
3626
3551
|
// return new string (page)
|
3627
|
-
...
|
3552
|
+
...newPointer,
|
3553
|
+
Opcodes.i32_from_u,
|
3628
3554
|
...setLastType(scope, TYPES.string)
|
3629
3555
|
],
|
3630
3556
|
[TYPES.bytestring]: [
|
3631
3557
|
// setup new/out array
|
3632
3558
|
...newOut,
|
3633
|
-
[ Opcodes.drop ],
|
3634
3559
|
|
3635
|
-
|
3560
|
+
// set length to 1
|
3561
|
+
...number(1, Valtype.i32),
|
3562
|
+
[ Opcodes.i32_store, 0, 0 ],
|
3563
|
+
|
3564
|
+
// use as pointer for store later
|
3565
|
+
...newPointer,
|
3636
3566
|
|
3637
3567
|
...property,
|
3638
3568
|
Opcodes.i32_to_u,
|
3639
3569
|
|
3640
|
-
...
|
3641
|
-
|
3642
|
-
|
3643
|
-
[ Opcodes.i32_add ]
|
3644
|
-
]),
|
3570
|
+
...object,
|
3571
|
+
Opcodes.i32_to_u,
|
3572
|
+
[ Opcodes.i32_add ],
|
3645
3573
|
|
3646
3574
|
// load current string ind {arg}
|
3647
|
-
[ Opcodes.i32_load8_u, 0,
|
3575
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
3648
3576
|
|
3649
3577
|
// store to new string ind 0
|
3650
|
-
[ Opcodes.i32_store8, 0,
|
3578
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
3651
3579
|
|
3652
3580
|
// return new string (page)
|
3653
|
-
...
|
3581
|
+
...newPointer,
|
3582
|
+
Opcodes.i32_from_u,
|
3654
3583
|
...setLastType(scope, TYPES.bytestring)
|
3655
3584
|
],
|
3656
3585
|
|
@@ -3795,9 +3724,9 @@ const internalConstrs = {
|
|
3795
3724
|
|
3796
3725
|
// new Array(n)
|
3797
3726
|
|
3798
|
-
const [ , pointer ] = makeArray(scope, {
|
3727
|
+
const [ out, pointer ] = makeArray(scope, {
|
3799
3728
|
rawElements: new Array(0)
|
3800
|
-
}, global, name, true);
|
3729
|
+
}, global, name, true, undefined, true);
|
3801
3730
|
|
3802
3731
|
const arg = decl.arguments[0] ?? DEFAULT_VALUE;
|
3803
3732
|
|
@@ -3806,12 +3735,13 @@ const internalConstrs = {
|
|
3806
3735
|
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeThrow', 'Invalid array length', true);
|
3807
3736
|
|
3808
3737
|
return [
|
3809
|
-
...
|
3738
|
+
...out,
|
3810
3739
|
...generate(scope, arg, global, name),
|
3811
3740
|
Opcodes.i32_to_u,
|
3812
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
3741
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3813
3742
|
|
3814
|
-
...
|
3743
|
+
...pointer,
|
3744
|
+
Opcodes.i32_from_u
|
3815
3745
|
];
|
3816
3746
|
},
|
3817
3747
|
type: TYPES.array,
|
@@ -3960,8 +3890,9 @@ const internalConstrs = {
|
|
3960
3890
|
};
|
3961
3891
|
|
3962
3892
|
export default program => {
|
3963
|
-
globals = {
|
3964
|
-
|
3893
|
+
globals = {
|
3894
|
+
['#ind']: 0
|
3895
|
+
};
|
3965
3896
|
tags = [];
|
3966
3897
|
exceptions = [];
|
3967
3898
|
funcs = [];
|
@@ -3994,6 +3925,7 @@ export default program => {
|
|
3994
3925
|
builtinFuncs = new BuiltinFuncs();
|
3995
3926
|
builtinVars = new BuiltinVars();
|
3996
3927
|
prototypeFuncs = new PrototypeFuncs();
|
3928
|
+
allocator = Allocator(Prefs.allocator ?? 'static');
|
3997
3929
|
|
3998
3930
|
program.id = { name: 'main' };
|
3999
3931
|
|
@@ -4036,6 +3968,8 @@ export default program => {
|
|
4036
3968
|
else main.returns = [];
|
4037
3969
|
}
|
4038
3970
|
|
3971
|
+
delete globals['#ind'];
|
3972
|
+
|
4039
3973
|
// if blank main func and other exports, remove it
|
4040
3974
|
if (main.wasm.length === 0 && funcs.reduce((acc, x) => acc + (x.export ? 1 : 0), 0) > 1) funcs.splice(main.index - importedFuncs.length, 1);
|
4041
3975
|
|