porffor 0.16.0-fe07da0f4 → 0.17.0-418ce1445
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 +2 -2
- package/README.md +5 -17
- package/compiler/2c.js +123 -75
- package/compiler/allocators.js +128 -0
- package/compiler/assemble.js +12 -5
- package/compiler/builtins/array.ts +72 -5
- package/compiler/builtins/base64.ts +25 -23
- package/compiler/builtins/date.ts +3 -30
- package/compiler/builtins/number.ts +10 -21
- package/compiler/builtins/porffor.d.ts +10 -0
- package/compiler/builtins/set.ts +2 -5
- package/compiler/builtins/string_f64.ts +10 -0
- package/compiler/builtins/z_ecma262.ts +62 -0
- package/compiler/builtins.js +26 -6
- package/compiler/codegen.js +328 -373
- package/compiler/cyclone.js +535 -0
- package/compiler/decompile.js +3 -1
- package/compiler/generated_builtins.js +143 -77
- package/compiler/havoc.js +93 -0
- package/compiler/index.js +104 -7
- package/compiler/opt.js +10 -44
- package/compiler/parse.js +2 -8
- package/compiler/pgo.js +212 -0
- package/compiler/precompile.js +12 -7
- package/compiler/prefs.js +8 -4
- package/compiler/prototype.js +34 -43
- package/compiler/wasmSpec.js +2 -2
- package/compiler/wrap.js +55 -13
- package/package.json +3 -5
- package/runner/index.js +26 -11
- /package/runner/{profiler.js → profile.js} +0 -0
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
|
+
}, assign ? false : global, assign ? undefined : 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
|
@@ -1014,12 +958,9 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
1014
958
|
[ Opcodes.end ],
|
1015
959
|
]));
|
1016
960
|
|
1017
|
-
//
|
1018
|
-
|
1019
|
-
|
1020
|
-
// endOut.push(stringOnly([ Opcodes.end ]));
|
1021
|
-
endOut.unshift(stringOnly([ Opcodes.end ]));
|
1022
|
-
// }
|
961
|
+
// add a surrounding block
|
962
|
+
startOut.push(stringOnly([ Opcodes.block, Valtype.i32 ]));
|
963
|
+
endOut.unshift(stringOnly([ Opcodes.end ]));
|
1023
964
|
}
|
1024
965
|
|
1025
966
|
return finalize([
|
@@ -1054,7 +995,7 @@ const asmFuncToAsm = (func, scope) => {
|
|
1054
995
|
});
|
1055
996
|
};
|
1056
997
|
|
1057
|
-
const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes = [], globalInits, returns, returnType, localNames = [], globalNames = [], data: _data = [], table = false }) => {
|
998
|
+
const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes = [], globalInits = [], returns, returnType, localNames = [], globalNames = [], data: _data = [], table = false }) => {
|
1058
999
|
const existing = funcs.find(x => x.name === name);
|
1059
1000
|
if (existing) return existing;
|
1060
1001
|
|
@@ -1068,7 +1009,7 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1068
1009
|
|
1069
1010
|
for (const x of _data) {
|
1070
1011
|
const copy = { ...x };
|
1071
|
-
copy.offset += pages.size * pageSize;
|
1012
|
+
if (copy.offset != null) copy.offset += pages.size * pageSize;
|
1072
1013
|
data.push(copy);
|
1073
1014
|
}
|
1074
1015
|
|
@@ -1078,7 +1019,7 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1078
1019
|
locals,
|
1079
1020
|
localInd: allLocals.length,
|
1080
1021
|
returns,
|
1081
|
-
returnType
|
1022
|
+
returnType,
|
1082
1023
|
internal: true,
|
1083
1024
|
index: currentFuncIndex++,
|
1084
1025
|
table
|
@@ -1091,9 +1032,9 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1091
1032
|
|
1092
1033
|
let baseGlobalIdx, i = 0;
|
1093
1034
|
for (const type of globalTypes) {
|
1094
|
-
if (baseGlobalIdx === undefined) baseGlobalIdx =
|
1035
|
+
if (baseGlobalIdx === undefined) baseGlobalIdx = globals['#ind'];
|
1095
1036
|
|
1096
|
-
globals[globalNames[i] ?? `${name}_global_${i}`] = { idx:
|
1037
|
+
globals[globalNames[i] ?? `${name}_global_${i}`] = { idx: globals['#ind']++, type, init: globalInits[i] ?? 0 };
|
1097
1038
|
i++;
|
1098
1039
|
}
|
1099
1040
|
|
@@ -1106,11 +1047,15 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1106
1047
|
}
|
1107
1048
|
}
|
1108
1049
|
|
1109
|
-
if (table)
|
1110
|
-
|
1111
|
-
inst.
|
1112
|
-
|
1050
|
+
if (table) {
|
1051
|
+
for (const inst of wasm) {
|
1052
|
+
if (inst[0] === Opcodes.i32_load16_u && inst.at(-1) === 'read_argc') {
|
1053
|
+
inst.splice(2, 99);
|
1054
|
+
inst.push(...unsignedLEB128(allocPage({}, 'func argc lut') * pageSize));
|
1055
|
+
}
|
1113
1056
|
}
|
1057
|
+
|
1058
|
+
funcs.table = true;
|
1114
1059
|
}
|
1115
1060
|
|
1116
1061
|
func.wasm = wasm;
|
@@ -1254,7 +1199,7 @@ const getNodeType = (scope, node) => {
|
|
1254
1199
|
const func = funcs.find(x => x.name === name);
|
1255
1200
|
|
1256
1201
|
if (func) {
|
1257
|
-
if (func.returnType) return func.returnType;
|
1202
|
+
if (func.returnType != null) return func.returnType;
|
1258
1203
|
}
|
1259
1204
|
|
1260
1205
|
if (builtinFuncs[name] && !builtinFuncs[name].typedReturns) return builtinFuncs[name].returnType ?? TYPES.number;
|
@@ -1270,15 +1215,7 @@ const getNodeType = (scope, node) => {
|
|
1270
1215
|
const func = spl[spl.length - 1];
|
1271
1216
|
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
|
1272
1217
|
if (protoFuncs.length === 1) {
|
1273
|
-
if (protoFuncs[0].returnType) return protoFuncs[0].returnType;
|
1274
|
-
}
|
1275
|
-
|
1276
|
-
if (protoFuncs.length > 0) {
|
1277
|
-
if (scope.locals['#last_type']) return getLastType(scope);
|
1278
|
-
|
1279
|
-
// presume
|
1280
|
-
// todo: warn here?
|
1281
|
-
return TYPES.number;
|
1218
|
+
if (protoFuncs[0].returnType != null) return protoFuncs[0].returnType;
|
1282
1219
|
}
|
1283
1220
|
}
|
1284
1221
|
|
@@ -1326,7 +1263,15 @@ const getNodeType = (scope, node) => {
|
|
1326
1263
|
}
|
1327
1264
|
|
1328
1265
|
if (node.type === 'AssignmentExpression') {
|
1329
|
-
|
1266
|
+
const op = node.operator.slice(0, -1) || '=';
|
1267
|
+
if (op === '=') return getNodeType(scope, node.right);
|
1268
|
+
|
1269
|
+
return getNodeType(scope, {
|
1270
|
+
type: ['||', '&&', '??'].includes(op) ? 'LogicalExpression' : 'BinaryExpression',
|
1271
|
+
left: node.left,
|
1272
|
+
right: node.right,
|
1273
|
+
operator: op
|
1274
|
+
});
|
1330
1275
|
}
|
1331
1276
|
|
1332
1277
|
if (node.type === 'ArrayExpression') {
|
@@ -1345,23 +1290,6 @@ const getNodeType = (scope, node) => {
|
|
1345
1290
|
if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) return TYPES.bytestring;
|
1346
1291
|
|
1347
1292
|
return TYPES.number;
|
1348
|
-
|
1349
|
-
// todo: string concat types
|
1350
|
-
// if (node.operator !== '+') return TYPES.number;
|
1351
|
-
// else return [
|
1352
|
-
// // if left is string
|
1353
|
-
// ...getNodeType(scope, node.left),
|
1354
|
-
// ...number(TYPES.string, Valtype.i32),
|
1355
|
-
// [ Opcodes.i32_eq ],
|
1356
|
-
|
1357
|
-
// // if right is string
|
1358
|
-
// ...getNodeType(scope, node.right),
|
1359
|
-
// ...number(TYPES.string, Valtype.i32),
|
1360
|
-
// [ Opcodes.i32_eq ],
|
1361
|
-
|
1362
|
-
// // if either are true
|
1363
|
-
// [ Opcodes.i32_or ],
|
1364
|
-
// ];
|
1365
1293
|
}
|
1366
1294
|
|
1367
1295
|
if (node.type === 'UnaryExpression') {
|
@@ -1381,7 +1309,6 @@ const getNodeType = (scope, node) => {
|
|
1381
1309
|
if (Prefs.fastLength) return TYPES.number;
|
1382
1310
|
}
|
1383
1311
|
|
1384
|
-
|
1385
1312
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1386
1313
|
if (objectKnownType != null) {
|
1387
1314
|
if (name === 'length') {
|
@@ -1392,7 +1319,6 @@ const getNodeType = (scope, node) => {
|
|
1392
1319
|
if (node.computed) {
|
1393
1320
|
if (objectKnownType === TYPES.string) return TYPES.string;
|
1394
1321
|
if (objectKnownType === TYPES.bytestring) return TYPES.bytestring;
|
1395
|
-
if (objectKnownType === TYPES.array) return TYPES.number;
|
1396
1322
|
}
|
1397
1323
|
}
|
1398
1324
|
|
@@ -1458,10 +1384,10 @@ const countLeftover = wasm => {
|
|
1458
1384
|
|
1459
1385
|
if (depth === 0)
|
1460
1386
|
if ([Opcodes.throw, Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1461
|
-
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] <
|
1387
|
+
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)) {}
|
1462
1388
|
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++;
|
1463
1389
|
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1464
|
-
else if (Opcodes.memory_copy[0]
|
1390
|
+
else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
|
1465
1391
|
else if (inst[0] === Opcodes.return) count = 0;
|
1466
1392
|
else if (inst[0] === Opcodes.call) {
|
1467
1393
|
let func = funcs.find(x => x.index === inst[1]);
|
@@ -1733,7 +1659,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1733
1659
|
}, generate(scope, decl.arguments[0] ?? DEFAULT_VALUE), getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE), protoLocal, protoLocal2, (length, itemType) => {
|
1734
1660
|
return makeArray(scope, {
|
1735
1661
|
rawElements: new Array(length)
|
1736
|
-
}, _global, _name, true, itemType);
|
1662
|
+
}, _global, _name, true, itemType, true);
|
1737
1663
|
}, () => {
|
1738
1664
|
optUnused = true;
|
1739
1665
|
return unusedValue;
|
@@ -1815,7 +1741,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1815
1741
|
f64_store: { imms: 2, args: [ true, false ], returns: 0 },
|
1816
1742
|
|
1817
1743
|
// value
|
1818
|
-
i32_const: { imms: 1, args: [], returns:
|
1744
|
+
i32_const: { imms: 1, args: [], returns: 0 },
|
1819
1745
|
};
|
1820
1746
|
|
1821
1747
|
const opName = name.slice('__Porffor_wasm_'.length);
|
@@ -1900,7 +1826,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1900
1826
|
if (indirectMode === 'strict') {
|
1901
1827
|
return typeSwitch(scope, getNodeType(scope, decl.callee), {
|
1902
1828
|
[TYPES.function]: [
|
1903
|
-
...
|
1829
|
+
...out,
|
1904
1830
|
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
1905
1831
|
Opcodes.i32_to_u,
|
1906
1832
|
[ Opcodes.call_indirect, args.length, 0 ],
|
@@ -1978,7 +1904,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1978
1904
|
const func = funcs[idx - importedFuncs.length]; // idx === scope.index ? scope : funcs.find(x => x.index === idx);
|
1979
1905
|
const userFunc = func && !func.internal;
|
1980
1906
|
const typedParams = userFunc || builtinFuncs[name]?.typedParams;
|
1981
|
-
const typedReturns = (
|
1907
|
+
const typedReturns = (userFunc && func.returnType == null) || builtinFuncs[name]?.typedReturns;
|
1982
1908
|
const paramCount = func && (typedParams ? func.params.length / 2 : func.params.length);
|
1983
1909
|
|
1984
1910
|
let args = decl.arguments;
|
@@ -2006,13 +1932,18 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2006
1932
|
continue;
|
2007
1933
|
}
|
2008
1934
|
|
2009
|
-
if (valtypeBinary !== Valtype.i32 &&
|
2010
|
-
(
|
2011
|
-
|
2012
|
-
)) {
|
1935
|
+
if (valtypeBinary !== Valtype.i32 &&
|
1936
|
+
(func && func.params[i * (typedParams ? 2 : 1)] === Valtype.i32)
|
1937
|
+
) {
|
2013
1938
|
out.push(Opcodes.i32_to);
|
2014
1939
|
}
|
2015
1940
|
|
1941
|
+
if (valtypeBinary === Valtype.i32 &&
|
1942
|
+
(func && func.params[i * (typedParams ? 2 : 1)] === Valtype.f64)
|
1943
|
+
) {
|
1944
|
+
out.push([ Opcodes.f64_convert_i32_s ]);
|
1945
|
+
}
|
1946
|
+
|
2016
1947
|
if (typedParams) out = out.concat(getNodeType(scope, arg));
|
2017
1948
|
}
|
2018
1949
|
|
@@ -2034,6 +1965,10 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2034
1965
|
out.push(Opcodes.i32_from);
|
2035
1966
|
}
|
2036
1967
|
|
1968
|
+
if (builtinFuncs[name] && builtinFuncs[name].returns?.[0] === Valtype.f64 && valtypeBinary === Valtype.i32) {
|
1969
|
+
out.push(Opcodes.i32_trunc_sat_f64_s);
|
1970
|
+
}
|
1971
|
+
|
2037
1972
|
return out;
|
2038
1973
|
};
|
2039
1974
|
|
@@ -2057,9 +1992,9 @@ const generateNew = (scope, decl, _global, _name) => {
|
|
2057
1992
|
if (
|
2058
1993
|
(builtinFuncs[name] && !builtinFuncs[name].constr) ||
|
2059
1994
|
(internalConstrs[name] && builtinFuncs[name].notConstr)
|
2060
|
-
) return internalThrow(scope, 'TypeError', `${name} is not a constructor
|
1995
|
+
) return internalThrow(scope, 'TypeError', `${name} is not a constructor`, true);
|
2061
1996
|
|
2062
|
-
if (!builtinFuncs[name]) return todo(scope, `new statement is not supported yet
|
1997
|
+
if (!builtinFuncs[name]) return todo(scope, `new statement is not supported yet`, true); // return todo(scope, `new statement is not supported yet (new ${unhackName(name)})`);
|
2063
1998
|
|
2064
1999
|
return generateCall(scope, decl, _global, _name);
|
2065
2000
|
};
|
@@ -2123,7 +2058,6 @@ const brTable = (input, bc, returns) => {
|
|
2123
2058
|
}
|
2124
2059
|
|
2125
2060
|
for (let i = 0; i < count; i++) {
|
2126
|
-
// if (i === 0) out.push([ Opcodes.block, returns, 'br table start' ]);
|
2127
2061
|
if (i === 0) out.push([ Opcodes.block, returns ]);
|
2128
2062
|
else out.push([ Opcodes.block, Blocktype.void ]);
|
2129
2063
|
}
|
@@ -2157,10 +2091,8 @@ const brTable = (input, bc, returns) => {
|
|
2157
2091
|
[ Opcodes.br_table, ...encodeVector(table), 0 ]
|
2158
2092
|
);
|
2159
2093
|
|
2160
|
-
//
|
2161
|
-
// (
|
2162
|
-
// dm me and if you are correct and the first person
|
2163
|
-
// I will somehow shout you out or something
|
2094
|
+
// sort the wrong way and then reverse
|
2095
|
+
// so strings ('default') are at the start before any numbers
|
2164
2096
|
const orderedBc = keys.sort((a, b) => b - a).reverse();
|
2165
2097
|
|
2166
2098
|
br = count - 1;
|
@@ -2186,10 +2118,10 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
|
2186
2118
|
return bc[known] ?? bc.default;
|
2187
2119
|
}
|
2188
2120
|
|
2189
|
-
if (Prefs.
|
2121
|
+
if (Prefs.typeswitchBrtable)
|
2190
2122
|
return brTable(type, bc, returns);
|
2191
2123
|
|
2192
|
-
const tmp = localTmp(scope, '#typeswitch_tmp', Valtype.i32);
|
2124
|
+
const tmp = localTmp(scope, '#typeswitch_tmp' + (Prefs.typeswitchUniqueTmp ? randId() : ''), Valtype.i32);
|
2193
2125
|
const out = [
|
2194
2126
|
...type,
|
2195
2127
|
[ Opcodes.local_set, tmp ],
|
@@ -2241,11 +2173,11 @@ const allocVar = (scope, name, global = false, type = true) => {
|
|
2241
2173
|
return target[name].idx;
|
2242
2174
|
}
|
2243
2175
|
|
2244
|
-
let idx = global ?
|
2176
|
+
let idx = global ? globals['#ind']++ : scope.localInd++;
|
2245
2177
|
target[name] = { idx, type: valtypeBinary };
|
2246
2178
|
|
2247
2179
|
if (type) {
|
2248
|
-
let typeIdx = global ?
|
2180
|
+
let typeIdx = global ? globals['#ind']++ : scope.localInd++;
|
2249
2181
|
target[name + '#type'] = { idx: typeIdx, type: Valtype.i32, name };
|
2250
2182
|
}
|
2251
2183
|
|
@@ -2338,24 +2270,10 @@ const generateVar = (scope, decl) => {
|
|
2338
2270
|
}
|
2339
2271
|
|
2340
2272
|
if (x.init) {
|
2341
|
-
|
2342
|
-
// // let a = function () { ... }
|
2343
|
-
// x.init.id = { name };
|
2344
|
-
|
2345
|
-
// const func = generateFunc(scope, x.init);
|
2346
|
-
|
2347
|
-
// out.push(
|
2348
|
-
// ...number(func.index - importedFuncs.length),
|
2349
|
-
// [ global ? Opcodes.global_set : Opcodes.local_set, idx ],
|
2350
|
-
|
2351
|
-
// ...setType(scope, name, TYPES.function)
|
2352
|
-
// );
|
2353
|
-
|
2354
|
-
// continue;
|
2355
|
-
// }
|
2273
|
+
const alreadyArray = scope.arrays?.get(name) != null;
|
2356
2274
|
|
2357
2275
|
const generated = generate(scope, x.init, global, name);
|
2358
|
-
if (scope.arrays?.get(name) != null) {
|
2276
|
+
if (!alreadyArray && scope.arrays?.get(name) != null) {
|
2359
2277
|
// hack to set local as pointer before
|
2360
2278
|
out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2361
2279
|
if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
|
@@ -2407,19 +2325,12 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2407
2325
|
|
2408
2326
|
// hack: .length setter
|
2409
2327
|
if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
|
2410
|
-
const name = decl.left.object.name;
|
2411
|
-
const pointer = scope.arrays?.get(name);
|
2412
|
-
|
2413
|
-
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2414
|
-
|
2415
2328
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2416
2329
|
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2417
2330
|
|
2418
2331
|
return [
|
2419
|
-
...(
|
2420
|
-
|
2421
|
-
Opcodes.i32_to_u
|
2422
|
-
]),
|
2332
|
+
...generate(scope, decl.left.object),
|
2333
|
+
Opcodes.i32_to_u,
|
2423
2334
|
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2424
2335
|
|
2425
2336
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
@@ -2430,7 +2341,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2430
2341
|
[ Opcodes.local_tee, newValueTmp ],
|
2431
2342
|
|
2432
2343
|
Opcodes.i32_to_u,
|
2433
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
2344
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2434
2345
|
|
2435
2346
|
[ Opcodes.local_get, newValueTmp ]
|
2436
2347
|
];
|
@@ -2438,21 +2349,14 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2438
2349
|
|
2439
2350
|
// arr[i]
|
2440
2351
|
if (decl.left.type === 'MemberExpression' && decl.left.computed) {
|
2441
|
-
const name = decl.left.object.name;
|
2442
|
-
const pointer = scope.arrays?.get(name);
|
2443
|
-
|
2444
|
-
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2445
|
-
|
2446
2352
|
const newValueTmp = localTmp(scope, '__member_setter_val_tmp');
|
2447
2353
|
const pointerTmp = op === '=' ? -1 : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2448
2354
|
|
2449
2355
|
return [
|
2450
2356
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2451
2357
|
[TYPES.array]: [
|
2452
|
-
...(
|
2453
|
-
|
2454
|
-
Opcodes.i32_to_u
|
2455
|
-
]),
|
2358
|
+
...generate(scope, decl.left.object),
|
2359
|
+
Opcodes.i32_to_u,
|
2456
2360
|
|
2457
2361
|
// get index as valtype
|
2458
2362
|
...generate(scope, decl.left.property),
|
@@ -2461,39 +2365,22 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2461
2365
|
// turn into byte offset by * valtypeSize (4 for i32, 8 for i64/f64)
|
2462
2366
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
2463
2367
|
[ Opcodes.i32_mul ],
|
2464
|
-
|
2368
|
+
[ Opcodes.i32_add ],
|
2465
2369
|
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2466
2370
|
|
2467
2371
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2468
2372
|
[ Opcodes.local_get, pointerTmp ],
|
2469
|
-
[ Opcodes.load, 0,
|
2373
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ]
|
2470
2374
|
], generate(scope, decl.right), [
|
2471
2375
|
[ Opcodes.local_get, pointerTmp ],
|
2472
|
-
[ Opcodes.i32_load8_u, 0,
|
2376
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2473
2377
|
], getNodeType(scope, decl.right), false, name, true)),
|
2474
2378
|
[ Opcodes.local_tee, newValueTmp ],
|
2475
2379
|
|
2476
|
-
[ Opcodes.store, 0,
|
2380
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2477
2381
|
],
|
2478
2382
|
|
2479
2383
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2480
|
-
|
2481
|
-
// [TYPES.string]: [
|
2482
|
-
// // turn into byte offset by * sizeof i16
|
2483
|
-
// ...number(ValtypeSize.i16, Valtype.i32),
|
2484
|
-
// [ Opcodes.i32_mul ],
|
2485
|
-
// ...(aotPointer ? [] : [ [ Opcodes.i32_add ] ]),
|
2486
|
-
// ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2487
|
-
|
2488
|
-
// ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2489
|
-
// [ Opcodes.local_get, pointerTmp ],
|
2490
|
-
// [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2491
|
-
// ], generate(scope, decl.right), number(TYPES.string, Valtype.i32), getNodeType(scope, decl.right))),
|
2492
|
-
// [ Opcodes.local_tee, newValueTmp ],
|
2493
|
-
|
2494
|
-
// Opcodes.i32_to_u,
|
2495
|
-
// [ StoreOps.i16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
2496
|
-
// ]
|
2497
2384
|
}, Blocktype.void),
|
2498
2385
|
|
2499
2386
|
[ Opcodes.local_get, newValueTmp ]
|
@@ -2555,9 +2442,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2555
2442
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2556
2443
|
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
2557
2444
|
|
2558
|
-
|
2559
|
-
|
2560
|
-
...setType(scope, name, TYPES.number)
|
2445
|
+
...setType(scope, name, getNodeType(scope, decl))
|
2561
2446
|
];
|
2562
2447
|
};
|
2563
2448
|
|
@@ -2571,7 +2456,7 @@ const generateUnary = (scope, decl) => {
|
|
2571
2456
|
// * -1
|
2572
2457
|
|
2573
2458
|
if (decl.prefix && decl.argument.type === 'Literal' && typeof decl.argument.value === 'number') {
|
2574
|
-
// if
|
2459
|
+
// if -n, just return that as a const
|
2575
2460
|
return number(-1 * decl.argument.value);
|
2576
2461
|
}
|
2577
2462
|
|
@@ -2583,14 +2468,14 @@ const generateUnary = (scope, decl) => {
|
|
2583
2468
|
case '!':
|
2584
2469
|
const arg = decl.argument;
|
2585
2470
|
if (arg.type === 'UnaryExpression' && arg.operator === '!') {
|
2586
|
-
// !!x -> is x truthy
|
2471
|
+
// opt: !!x -> is x truthy
|
2587
2472
|
return truthy(scope, generate(scope, arg.argument), getNodeType(scope, arg.argument), false, false);
|
2588
2473
|
}
|
2474
|
+
|
2589
2475
|
// !=
|
2590
|
-
return falsy(scope, generate(scope,
|
2476
|
+
return falsy(scope, generate(scope, arg), getNodeType(scope, arg), false, false);
|
2591
2477
|
|
2592
2478
|
case '~':
|
2593
|
-
// todo: does not handle Infinity properly (should convert to 0) (but opt const converting saves us sometimes)
|
2594
2479
|
return [
|
2595
2480
|
...generate(scope, decl.argument),
|
2596
2481
|
Opcodes.i32_to,
|
@@ -2877,12 +2762,12 @@ const generateForOf = (scope, decl) => {
|
|
2877
2762
|
|
2878
2763
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2879
2764
|
// hack: this is naughty and will break things!
|
2880
|
-
let newOut = number(0, Valtype.
|
2765
|
+
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
2881
2766
|
if (pages.hasAnyString) {
|
2882
2767
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2883
2768
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2884
|
-
rawElements: new Array(
|
2885
|
-
}, isGlobal, leftName, true, 'i16');
|
2769
|
+
rawElements: new Array(0)
|
2770
|
+
}, isGlobal, leftName, true, 'i16', true);
|
2886
2771
|
}
|
2887
2772
|
|
2888
2773
|
// set type for local
|
@@ -2929,23 +2814,28 @@ const generateForOf = (scope, decl) => {
|
|
2929
2814
|
[TYPES.string]: [
|
2930
2815
|
...setType(scope, leftName, TYPES.string),
|
2931
2816
|
|
2932
|
-
[ Opcodes.loop, Blocktype.void ],
|
2933
|
-
|
2934
2817
|
// setup new/out array
|
2935
2818
|
...newOut,
|
2936
|
-
[ Opcodes.drop ],
|
2937
2819
|
|
2938
|
-
|
2820
|
+
// set length to 1
|
2821
|
+
...number(1, Valtype.i32),
|
2822
|
+
[ Opcodes.i32_store, 0, 0 ],
|
2823
|
+
|
2824
|
+
[ Opcodes.loop, Blocktype.void ],
|
2825
|
+
|
2826
|
+
// use as pointer for store later
|
2827
|
+
...newPointer,
|
2939
2828
|
|
2940
2829
|
// load current string ind {arg}
|
2941
2830
|
[ Opcodes.local_get, pointer ],
|
2942
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
2831
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2943
2832
|
|
2944
2833
|
// store to new string ind 0
|
2945
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
2834
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
2946
2835
|
|
2947
2836
|
// return new string (page)
|
2948
|
-
...
|
2837
|
+
...newPointer,
|
2838
|
+
Opcodes.i32_from_u,
|
2949
2839
|
|
2950
2840
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2951
2841
|
|
@@ -2977,25 +2867,30 @@ const generateForOf = (scope, decl) => {
|
|
2977
2867
|
[TYPES.bytestring]: [
|
2978
2868
|
...setType(scope, leftName, TYPES.bytestring),
|
2979
2869
|
|
2980
|
-
[ Opcodes.loop, Blocktype.void ],
|
2981
|
-
|
2982
2870
|
// setup new/out array
|
2983
2871
|
...newOut,
|
2984
|
-
[ Opcodes.drop ],
|
2985
2872
|
|
2986
|
-
|
2873
|
+
// set length to 1
|
2874
|
+
...number(1, Valtype.i32),
|
2875
|
+
[ Opcodes.i32_store, 0, 0 ],
|
2876
|
+
|
2877
|
+
[ Opcodes.loop, Blocktype.void ],
|
2878
|
+
|
2879
|
+
// use as pointer for store later
|
2880
|
+
...newPointer,
|
2987
2881
|
|
2988
2882
|
// load current string ind {arg}
|
2989
2883
|
[ Opcodes.local_get, pointer ],
|
2990
2884
|
[ Opcodes.local_get, counter ],
|
2991
2885
|
[ Opcodes.i32_add ],
|
2992
|
-
[ Opcodes.i32_load8_u, 0,
|
2886
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
2993
2887
|
|
2994
2888
|
// store to new string ind 0
|
2995
|
-
[ Opcodes.i32_store8, 0,
|
2889
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
2996
2890
|
|
2997
2891
|
// return new string (page)
|
2998
|
-
...
|
2892
|
+
...newPointer,
|
2893
|
+
Opcodes.i32_from_u,
|
2999
2894
|
|
3000
2895
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
3001
2896
|
|
@@ -3210,18 +3105,6 @@ const allocPage = (scope, reason, type) => {
|
|
3210
3105
|
scope.pages ??= new Map();
|
3211
3106
|
scope.pages.set(reason, { ind, type });
|
3212
3107
|
|
3213
|
-
if (Prefs.allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
|
3214
|
-
|
3215
|
-
return ind;
|
3216
|
-
};
|
3217
|
-
|
3218
|
-
// todo: add scope.pages
|
3219
|
-
const freePage = reason => {
|
3220
|
-
const { ind } = pages.get(reason);
|
3221
|
-
pages.delete(reason);
|
3222
|
-
|
3223
|
-
if (Prefs.allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
|
3224
|
-
|
3225
3108
|
return ind;
|
3226
3109
|
};
|
3227
3110
|
|
@@ -3259,39 +3142,58 @@ const compileBytes = (val, itemType) => {
|
|
3259
3142
|
}
|
3260
3143
|
};
|
3261
3144
|
|
3262
|
-
const
|
3263
|
-
|
3264
|
-
|
3265
|
-
|
3145
|
+
const makeData = (scope, elements, offset = null, itemType, initEmpty) => {
|
3146
|
+
const length = elements.length;
|
3147
|
+
|
3148
|
+
// if length is 0 memory/data will just be 0000... anyway
|
3149
|
+
if (length === 0) return false;
|
3150
|
+
|
3151
|
+
let bytes = compileBytes(length, 'i32');
|
3152
|
+
|
3153
|
+
if (!initEmpty) for (let i = 0; i < length; i++) {
|
3154
|
+
if (elements[i] == null) continue;
|
3266
3155
|
|
3267
|
-
|
3156
|
+
bytes.push(...compileBytes(elements[i], itemType));
|
3268
3157
|
}
|
3269
|
-
};
|
3270
3158
|
|
3271
|
-
const
|
3272
|
-
|
3159
|
+
const obj = { bytes };
|
3160
|
+
if (offset != null) obj.offset = offset;
|
3273
3161
|
|
3274
|
-
|
3162
|
+
const idx = data.push(obj) - 1;
|
3275
3163
|
|
3276
|
-
|
3277
|
-
|
3278
|
-
firstAssign = true;
|
3164
|
+
scope.data ??= [];
|
3165
|
+
scope.data.push(idx);
|
3279
3166
|
|
3280
|
-
|
3281
|
-
|
3167
|
+
return { idx, size: bytes.length };
|
3168
|
+
};
|
3282
3169
|
|
3283
|
-
|
3284
|
-
|
3285
|
-
else page = allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType);
|
3170
|
+
const printStaticStr = str => {
|
3171
|
+
const out = [];
|
3286
3172
|
|
3287
|
-
|
3288
|
-
|
3289
|
-
|
3173
|
+
for (let i = 0; i < str.length; i++) {
|
3174
|
+
out.push(
|
3175
|
+
// ...number(str.charCodeAt(i)),
|
3176
|
+
...number(str.charCodeAt(i), Valtype.i32),
|
3177
|
+
Opcodes.i32_from_u,
|
3178
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
3179
|
+
);
|
3290
3180
|
}
|
3291
3181
|
|
3292
|
-
|
3182
|
+
return out;
|
3183
|
+
};
|
3184
|
+
|
3185
|
+
const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false, itemType = valtype, intOut = false, typed = false) => {
|
3186
|
+
if (itemType !== 'i16' && itemType !== 'i8') {
|
3187
|
+
pages.hasArray = true;
|
3188
|
+
} else {
|
3189
|
+
pages.hasAnyString = true;
|
3190
|
+
if (itemType === 'i8') pages.hasByteString = true;
|
3191
|
+
else pages.hasString = true;
|
3192
|
+
}
|
3193
|
+
|
3194
|
+
const out = [];
|
3293
3195
|
|
3294
|
-
const
|
3196
|
+
const uniqueName = name === '$undeclared' ? name + randId() : name;
|
3295
3197
|
|
3296
3198
|
const useRawElements = !!decl.rawElements;
|
3297
3199
|
const elements = useRawElements ? decl.rawElements : decl.elements;
|
@@ -3299,46 +3201,81 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3299
3201
|
const valtype = itemTypeToValtype[itemType];
|
3300
3202
|
const length = elements.length;
|
3301
3203
|
|
3302
|
-
|
3303
|
-
// if length is 0 memory/data will just be 0000... anyway
|
3304
|
-
if (length !== 0) {
|
3305
|
-
let bytes = compileBytes(length, 'i32');
|
3204
|
+
const allocated = allocator.alloc({ scope, pages, globals, asmFunc, funcIndex }, uniqueName, { itemType });
|
3306
3205
|
|
3307
|
-
|
3308
|
-
|
3206
|
+
let pointer = allocated;
|
3207
|
+
if (allocator.constructor.name !== 'StaticAllocator') {
|
3208
|
+
// const tmp = localTmp(scope, '#makearray_pointer' + uniqueName, Valtype.i32);
|
3209
|
+
const tmp = localTmp(scope, '#makearray_pointer' + name, Valtype.i32);
|
3210
|
+
out.push(
|
3211
|
+
...allocated,
|
3212
|
+
[ Opcodes.local_set, tmp ]
|
3213
|
+
);
|
3214
|
+
|
3215
|
+
if (Prefs.runtimeAllocLog) out.push(
|
3216
|
+
...printStaticStr(`${name}: `),
|
3217
|
+
|
3218
|
+
[ Opcodes.local_get, tmp ],
|
3219
|
+
Opcodes.i32_from_u,
|
3220
|
+
[ Opcodes.call, 0 ],
|
3221
|
+
|
3222
|
+
...number(10),
|
3223
|
+
[ Opcodes.call, 1 ]
|
3224
|
+
);
|
3309
3225
|
|
3310
|
-
|
3226
|
+
pointer = [ [ Opcodes.local_get, tmp ] ];
|
3227
|
+
|
3228
|
+
if (Prefs.data && useRawElements) {
|
3229
|
+
const data = makeData(scope, elements, null, itemType, initEmpty);
|
3230
|
+
if (data) {
|
3231
|
+
// init data
|
3232
|
+
out.push(
|
3233
|
+
...pointer,
|
3234
|
+
...number(0, Valtype.i32),
|
3235
|
+
...number(data.size, Valtype.i32),
|
3236
|
+
[ ...Opcodes.memory_init, ...unsignedLEB128(data.idx), 0 ]
|
3237
|
+
);
|
3311
3238
|
}
|
3312
3239
|
|
3313
|
-
|
3314
|
-
|
3315
|
-
|
3316
|
-
|
3240
|
+
// return pointer in out
|
3241
|
+
out.push(
|
3242
|
+
...pointer,
|
3243
|
+
...(!intOut ? [ Opcodes.i32_from_u ] : [])
|
3244
|
+
);
|
3317
3245
|
|
3318
|
-
|
3319
|
-
scope.data.push(ind);
|
3246
|
+
return [ out, pointer ];
|
3320
3247
|
}
|
3248
|
+
} else {
|
3249
|
+
const rawPtr = read_signedLEB128(pointer[0].slice(1));
|
3321
3250
|
|
3322
|
-
|
3323
|
-
|
3251
|
+
scope.arrays ??= new Map();
|
3252
|
+
const firstAssign = !scope.arrays.has(uniqueName);
|
3253
|
+
if (firstAssign) scope.arrays.set(uniqueName, rawPtr);
|
3324
3254
|
|
3325
|
-
|
3326
|
-
|
3255
|
+
if (Prefs.data && firstAssign && useRawElements) {
|
3256
|
+
makeData(scope, elements, rawPtr, itemType, initEmpty);
|
3327
3257
|
|
3328
|
-
|
3329
|
-
|
3330
|
-
|
3331
|
-
|
3332
|
-
|
3333
|
-
|
3334
|
-
)
|
3258
|
+
// local value as pointer
|
3259
|
+
return [ number(rawPtr, intOut ? Valtype.i32 : valtypeBinary), pointer ];
|
3260
|
+
}
|
3261
|
+
|
3262
|
+
const local = global ? globals[name] : scope.locals[name];
|
3263
|
+
const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
|
3264
|
+
if (pointerTmp != null) {
|
3265
|
+
out.push(
|
3266
|
+
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
3267
|
+
Opcodes.i32_to_u,
|
3268
|
+
[ Opcodes.local_set, pointerTmp ]
|
3269
|
+
);
|
3270
|
+
|
3271
|
+
pointer = [ [ Opcodes.local_get, pointerTmp ] ];
|
3272
|
+
}
|
3335
3273
|
}
|
3336
3274
|
|
3337
|
-
const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
|
3338
3275
|
|
3339
3276
|
// store length
|
3340
3277
|
out.push(
|
3341
|
-
...
|
3278
|
+
...pointer,
|
3342
3279
|
...number(length, Valtype.i32),
|
3343
3280
|
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
|
3344
3281
|
);
|
@@ -3350,11 +3287,11 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3350
3287
|
|
3351
3288
|
const offset = ValtypeSize.i32 + i * sizePerEl;
|
3352
3289
|
out.push(
|
3353
|
-
...
|
3290
|
+
...pointer,
|
3354
3291
|
...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
|
3355
3292
|
[ storeOp, 0, ...unsignedLEB128(offset) ],
|
3356
3293
|
...(!typed ? [] : [ // typed presumes !useRawElements
|
3357
|
-
...
|
3294
|
+
...pointer,
|
3358
3295
|
...getNodeType(scope, elements[i]),
|
3359
3296
|
[ Opcodes.i32_store8, 0, ...unsignedLEB128(offset + ValtypeSize[itemType]) ]
|
3360
3297
|
])
|
@@ -3362,12 +3299,13 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3362
3299
|
}
|
3363
3300
|
|
3364
3301
|
// local value as pointer
|
3365
|
-
out.push(...
|
3302
|
+
out.push(...pointer);
|
3303
|
+
if (!intOut) out.push(Opcodes.i32_from_u);
|
3366
3304
|
|
3367
3305
|
return [ out, pointer ];
|
3368
3306
|
};
|
3369
3307
|
|
3370
|
-
const storeArray = (scope, array, index, element
|
3308
|
+
const storeArray = (scope, array, index, element) => {
|
3371
3309
|
if (!Array.isArray(element)) element = generate(scope, element);
|
3372
3310
|
if (typeof index === 'number') index = number(index);
|
3373
3311
|
|
@@ -3379,26 +3317,25 @@ const storeArray = (scope, array, index, element, aotPointer = null) => {
|
|
3379
3317
|
Opcodes.i32_to_u,
|
3380
3318
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3381
3319
|
[ Opcodes.i32_mul ],
|
3382
|
-
|
3383
|
-
|
3384
|
-
|
3385
|
-
|
3386
|
-
]),
|
3320
|
+
|
3321
|
+
...array,
|
3322
|
+
Opcodes.i32_to_u,
|
3323
|
+
[ Opcodes.i32_add ],
|
3387
3324
|
[ Opcodes.local_set, offset ],
|
3388
3325
|
|
3389
3326
|
// store value
|
3390
3327
|
[ Opcodes.local_get, offset ],
|
3391
3328
|
...generate(scope, element),
|
3392
|
-
[ Opcodes.store, 0,
|
3329
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
3393
3330
|
|
3394
3331
|
// store type
|
3395
3332
|
[ Opcodes.local_get, offset ],
|
3396
3333
|
...getNodeType(scope, element),
|
3397
|
-
[ Opcodes.i32_store8, 0,
|
3334
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3398
3335
|
];
|
3399
3336
|
};
|
3400
3337
|
|
3401
|
-
const loadArray = (scope, array, index
|
3338
|
+
const loadArray = (scope, array, index) => {
|
3402
3339
|
if (typeof index === 'number') index = number(index);
|
3403
3340
|
|
3404
3341
|
const offset = localTmp(scope, '#loadArray_offset', Valtype.i32);
|
@@ -3409,20 +3346,19 @@ const loadArray = (scope, array, index, aotPointer = null) => {
|
|
3409
3346
|
Opcodes.i32_to_u,
|
3410
3347
|
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
3411
3348
|
[ Opcodes.i32_mul ],
|
3412
|
-
|
3413
|
-
|
3414
|
-
|
3415
|
-
|
3416
|
-
]),
|
3349
|
+
|
3350
|
+
...array,
|
3351
|
+
Opcodes.i32_to_u,
|
3352
|
+
[ Opcodes.i32_add ],
|
3417
3353
|
[ Opcodes.local_set, offset ],
|
3418
3354
|
|
3419
3355
|
// load value
|
3420
3356
|
[ Opcodes.local_get, offset ],
|
3421
|
-
[ Opcodes.load, 0,
|
3357
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ],
|
3422
3358
|
|
3423
3359
|
// load type
|
3424
3360
|
[ Opcodes.local_get, offset ],
|
3425
|
-
[ Opcodes.i32_load8_u, 0,
|
3361
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
3426
3362
|
];
|
3427
3363
|
};
|
3428
3364
|
|
@@ -3454,7 +3390,7 @@ const makeString = (scope, str, global = false, name = '$undeclared', forceBytes
|
|
3454
3390
|
};
|
3455
3391
|
|
3456
3392
|
const generateArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false) => {
|
3457
|
-
return makeArray(scope, decl, global, name, initEmpty, valtype, true)[0];
|
3393
|
+
return makeArray(scope, decl, global, name, initEmpty, valtype, false, true)[0];
|
3458
3394
|
};
|
3459
3395
|
|
3460
3396
|
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
@@ -3473,9 +3409,6 @@ const withType = (scope, wasm, type) => [
|
|
3473
3409
|
|
3474
3410
|
const generateMember = (scope, decl, _global, _name) => {
|
3475
3411
|
const name = decl.object.name;
|
3476
|
-
const pointer = scope.arrays?.get(name);
|
3477
|
-
|
3478
|
-
const aotPointer = Prefs.aotPointerOpt && pointer;
|
3479
3412
|
|
3480
3413
|
// hack: .name
|
3481
3414
|
if (decl.property.name === 'name') {
|
@@ -3510,18 +3443,16 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3510
3443
|
}
|
3511
3444
|
|
3512
3445
|
if (builtinFuncs[name]) return withType(scope, number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length), TYPES.number);
|
3513
|
-
if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params), TYPES.number);
|
3446
|
+
if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params.length ?? importedFuncs[name].params), TYPES.number);
|
3514
3447
|
if (internalConstrs[name]) return withType(scope, number(internalConstrs[name].length ?? 0), TYPES.number);
|
3515
3448
|
|
3516
3449
|
if (Prefs.fastLength) {
|
3517
3450
|
// presume valid length object
|
3518
3451
|
return [
|
3519
|
-
...(
|
3520
|
-
|
3521
|
-
Opcodes.i32_to_u
|
3522
|
-
]),
|
3452
|
+
...generate(scope, decl.object),
|
3453
|
+
Opcodes.i32_to_u,
|
3523
3454
|
|
3524
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3455
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3525
3456
|
Opcodes.i32_from_u
|
3526
3457
|
];
|
3527
3458
|
}
|
@@ -3530,12 +3461,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3530
3461
|
const known = knownType(scope, type);
|
3531
3462
|
if (known != null) {
|
3532
3463
|
if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(known)) return [
|
3533
|
-
...(
|
3534
|
-
|
3535
|
-
Opcodes.i32_to_u
|
3536
|
-
]),
|
3464
|
+
...generate(scope, decl.object),
|
3465
|
+
Opcodes.i32_to_u,
|
3537
3466
|
|
3538
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3467
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3539
3468
|
Opcodes.i32_from_u
|
3540
3469
|
];
|
3541
3470
|
|
@@ -3545,12 +3474,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3545
3474
|
return [
|
3546
3475
|
...typeIsOneOf(getNodeType(scope, decl.object), [ TYPES.string, TYPES.bytestring, TYPES.array ]),
|
3547
3476
|
[ Opcodes.if, valtypeBinary ],
|
3548
|
-
...(
|
3549
|
-
|
3550
|
-
Opcodes.i32_to_u
|
3551
|
-
]),
|
3477
|
+
...generate(scope, decl.object),
|
3478
|
+
Opcodes.i32_to_u,
|
3552
3479
|
|
3553
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1,
|
3480
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3554
3481
|
Opcodes.i32_from_u,
|
3555
3482
|
|
3556
3483
|
...setLastType(scope, TYPES.number),
|
@@ -3593,25 +3520,29 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3593
3520
|
|
3594
3521
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3595
3522
|
// hack: this is naughty and will break things!
|
3596
|
-
let newOut = number(0,
|
3597
|
-
if (pages.hasAnyString) {
|
3523
|
+
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3524
|
+
if (pages.hasAnyString && knownType(scope, getNodeType(scope, decl.object)) !== TYPES.array) {
|
3525
|
+
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3598
3526
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3599
|
-
rawElements: new Array(
|
3600
|
-
}, _global, _name, true, 'i16');
|
3527
|
+
rawElements: new Array(0)
|
3528
|
+
}, _global, _name, true, 'i16', true);
|
3601
3529
|
}
|
3602
3530
|
|
3603
3531
|
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3604
3532
|
[TYPES.array]: [
|
3605
|
-
...loadArray(scope, object, property
|
3533
|
+
...loadArray(scope, object, property),
|
3606
3534
|
...setLastType(scope)
|
3607
3535
|
],
|
3608
|
-
|
3609
3536
|
[TYPES.string]: [
|
3610
3537
|
// setup new/out array
|
3611
3538
|
...newOut,
|
3612
|
-
[ Opcodes.drop ],
|
3613
3539
|
|
3614
|
-
|
3540
|
+
// set length to 1
|
3541
|
+
...number(1, Valtype.i32),
|
3542
|
+
[ Opcodes.i32_store, 0, 0 ],
|
3543
|
+
|
3544
|
+
// use as pointer for store later
|
3545
|
+
...newPointer,
|
3615
3546
|
|
3616
3547
|
...property,
|
3617
3548
|
Opcodes.i32_to_u,
|
@@ -3619,46 +3550,48 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3619
3550
|
...number(ValtypeSize.i16, Valtype.i32),
|
3620
3551
|
[ Opcodes.i32_mul ],
|
3621
3552
|
|
3622
|
-
...
|
3623
|
-
|
3624
|
-
|
3625
|
-
[ Opcodes.i32_add ]
|
3626
|
-
]),
|
3553
|
+
...object,
|
3554
|
+
Opcodes.i32_to_u,
|
3555
|
+
[ Opcodes.i32_add ],
|
3627
3556
|
|
3628
3557
|
// load current string ind {arg}
|
3629
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1,
|
3558
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3630
3559
|
|
3631
3560
|
// store to new string ind 0
|
3632
|
-
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1,
|
3561
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
3633
3562
|
|
3634
3563
|
// return new string (page)
|
3635
|
-
...
|
3564
|
+
...newPointer,
|
3565
|
+
Opcodes.i32_from_u,
|
3636
3566
|
...setLastType(scope, TYPES.string)
|
3637
3567
|
],
|
3638
3568
|
[TYPES.bytestring]: [
|
3639
3569
|
// setup new/out array
|
3640
3570
|
...newOut,
|
3641
|
-
[ Opcodes.drop ],
|
3642
3571
|
|
3643
|
-
|
3572
|
+
// set length to 1
|
3573
|
+
...number(1, Valtype.i32),
|
3574
|
+
[ Opcodes.i32_store, 0, 0 ],
|
3575
|
+
|
3576
|
+
// use as pointer for store later
|
3577
|
+
...newPointer,
|
3644
3578
|
|
3645
3579
|
...property,
|
3646
3580
|
Opcodes.i32_to_u,
|
3647
3581
|
|
3648
|
-
...
|
3649
|
-
|
3650
|
-
|
3651
|
-
[ Opcodes.i32_add ]
|
3652
|
-
]),
|
3582
|
+
...object,
|
3583
|
+
Opcodes.i32_to_u,
|
3584
|
+
[ Opcodes.i32_add ],
|
3653
3585
|
|
3654
3586
|
// load current string ind {arg}
|
3655
|
-
[ Opcodes.i32_load8_u, 0,
|
3587
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
|
3656
3588
|
|
3657
3589
|
// store to new string ind 0
|
3658
|
-
[ Opcodes.i32_store8, 0,
|
3590
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 ],
|
3659
3591
|
|
3660
3592
|
// return new string (page)
|
3661
|
-
...
|
3593
|
+
...newPointer,
|
3594
|
+
Opcodes.i32_from_u,
|
3662
3595
|
...setLastType(scope, TYPES.bytestring)
|
3663
3596
|
],
|
3664
3597
|
|
@@ -3666,7 +3599,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3666
3599
|
});
|
3667
3600
|
};
|
3668
3601
|
|
3669
|
-
const randId = () => Math.random().toString(16).slice(
|
3602
|
+
const randId = () => Math.random().toString(16).slice(1, -2).padEnd(12, '0');
|
3670
3603
|
|
3671
3604
|
const objectHack = node => {
|
3672
3605
|
if (!node) return node;
|
@@ -3718,7 +3651,7 @@ const generateFunc = (scope, decl) => {
|
|
3718
3651
|
if (decl.async) return todo(scope, 'async functions are not supported');
|
3719
3652
|
if (decl.generator) return todo(scope, 'generator functions are not supported');
|
3720
3653
|
|
3721
|
-
const name = decl.id ? decl.id.name : `
|
3654
|
+
const name = decl.id ? decl.id.name : `anonymous${randId()}`;
|
3722
3655
|
const params = decl.params ?? [];
|
3723
3656
|
|
3724
3657
|
// TODO: share scope/locals between !!!
|
@@ -3732,6 +3665,9 @@ const generateFunc = (scope, decl) => {
|
|
3732
3665
|
index: currentFuncIndex++
|
3733
3666
|
};
|
3734
3667
|
|
3668
|
+
funcIndex[name] = func.index;
|
3669
|
+
funcs.push(func);
|
3670
|
+
|
3735
3671
|
if (typedInput && decl.returnType) {
|
3736
3672
|
const { type } = extractTypeAnnotation(decl.returnType);
|
3737
3673
|
// if (type != null && !Prefs.indirectCalls) {
|
@@ -3741,12 +3677,26 @@ const generateFunc = (scope, decl) => {
|
|
3741
3677
|
}
|
3742
3678
|
}
|
3743
3679
|
|
3680
|
+
const defaultValues = {};
|
3744
3681
|
for (let i = 0; i < params.length; i++) {
|
3745
|
-
|
3682
|
+
let name;
|
3683
|
+
const x = params[i];
|
3684
|
+
switch (x.type) {
|
3685
|
+
case 'Identifier': {
|
3686
|
+
name = x.name;
|
3687
|
+
break;
|
3688
|
+
}
|
3689
|
+
|
3690
|
+
case 'AssignmentPattern': {
|
3691
|
+
name = x.left.name;
|
3692
|
+
defaultValues[name] = x.right;
|
3693
|
+
break;
|
3694
|
+
}
|
3695
|
+
}
|
3696
|
+
|
3746
3697
|
// if (name == null) return todo('non-identifier args are not supported');
|
3747
3698
|
|
3748
3699
|
allocVar(func, name, false);
|
3749
|
-
|
3750
3700
|
if (typedInput && params[i].typeAnnotation) {
|
3751
3701
|
addVarMetadata(func, name, false, extractTypeAnnotation(params[i]));
|
3752
3702
|
}
|
@@ -3763,11 +3713,22 @@ const generateFunc = (scope, decl) => {
|
|
3763
3713
|
};
|
3764
3714
|
}
|
3765
3715
|
|
3766
|
-
|
3767
|
-
|
3716
|
+
const prelude = [];
|
3717
|
+
for (const x in defaultValues) {
|
3718
|
+
prelude.push(
|
3719
|
+
...getType(func, x),
|
3720
|
+
...number(TYPES.undefined, Valtype.i32),
|
3721
|
+
[ Opcodes.i32_eq ],
|
3722
|
+
[ Opcodes.if, Blocktype.void ],
|
3723
|
+
...generate(func, defaultValues[x], false, x),
|
3724
|
+
[ Opcodes.local_set, func.locals[x].idx ],
|
3768
3725
|
|
3769
|
-
|
3770
|
-
|
3726
|
+
...setType(func, x, getNodeType(scope, defaultValues[x])),
|
3727
|
+
[ Opcodes.end ]
|
3728
|
+
);
|
3729
|
+
}
|
3730
|
+
|
3731
|
+
const wasm = func.wasm = prelude.concat(generate(func, body));
|
3771
3732
|
|
3772
3733
|
if (name === 'main') func.gotLastType = true;
|
3773
3734
|
|
@@ -3803,9 +3764,9 @@ const internalConstrs = {
|
|
3803
3764
|
|
3804
3765
|
// new Array(n)
|
3805
3766
|
|
3806
|
-
const [ , pointer ] = makeArray(scope, {
|
3767
|
+
const [ out, pointer ] = makeArray(scope, {
|
3807
3768
|
rawElements: new Array(0)
|
3808
|
-
}, global, name, true);
|
3769
|
+
}, global, name, true, undefined, true);
|
3809
3770
|
|
3810
3771
|
const arg = decl.arguments[0] ?? DEFAULT_VALUE;
|
3811
3772
|
|
@@ -3814,12 +3775,13 @@ const internalConstrs = {
|
|
3814
3775
|
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeThrow', 'Invalid array length', true);
|
3815
3776
|
|
3816
3777
|
return [
|
3817
|
-
...
|
3778
|
+
...out,
|
3818
3779
|
...generate(scope, arg, global, name),
|
3819
3780
|
Opcodes.i32_to_u,
|
3820
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
3781
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3821
3782
|
|
3822
|
-
...
|
3783
|
+
...pointer,
|
3784
|
+
Opcodes.i32_from_u
|
3823
3785
|
];
|
3824
3786
|
},
|
3825
3787
|
type: TYPES.array,
|
@@ -3968,8 +3930,9 @@ const internalConstrs = {
|
|
3968
3930
|
};
|
3969
3931
|
|
3970
3932
|
export default program => {
|
3971
|
-
globals = {
|
3972
|
-
|
3933
|
+
globals = {
|
3934
|
+
['#ind']: 0
|
3935
|
+
};
|
3973
3936
|
tags = [];
|
3974
3937
|
exceptions = [];
|
3975
3938
|
funcs = [];
|
@@ -3979,19 +3942,8 @@ export default program => {
|
|
3979
3942
|
data = [];
|
3980
3943
|
currentFuncIndex = importedFuncs.length;
|
3981
3944
|
|
3982
|
-
globalThis.valtype = 'f64';
|
3983
|
-
|
3984
|
-
const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
|
3985
|
-
if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
|
3986
|
-
|
3987
|
-
globalThis.valtypeBinary = Valtype[valtype];
|
3988
|
-
|
3989
3945
|
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
3990
3946
|
|
3991
|
-
globalThis.pageSize = PageSize;
|
3992
|
-
const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
|
3993
|
-
if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
|
3994
|
-
|
3995
3947
|
// set generic opcodes for current valtype
|
3996
3948
|
Opcodes.const = [ Opcodes.i32_const, Opcodes.i64_const, Opcodes.f64_const ][valtypeInd];
|
3997
3949
|
Opcodes.eq = [ Opcodes.i32_eq, Opcodes.i64_eq, Opcodes.f64_eq ][valtypeInd];
|
@@ -4013,6 +3965,7 @@ export default program => {
|
|
4013
3965
|
builtinFuncs = new BuiltinFuncs();
|
4014
3966
|
builtinVars = new BuiltinVars();
|
4015
3967
|
prototypeFuncs = new PrototypeFuncs();
|
3968
|
+
allocator = makeAllocator(Prefs.allocator ?? 'static');
|
4016
3969
|
|
4017
3970
|
program.id = { name: 'main' };
|
4018
3971
|
|
@@ -4055,6 +4008,8 @@ export default program => {
|
|
4055
4008
|
else main.returns = [];
|
4056
4009
|
}
|
4057
4010
|
|
4011
|
+
delete globals['#ind'];
|
4012
|
+
|
4058
4013
|
// if blank main func and other exports, remove it
|
4059
4014
|
if (main.wasm.length === 0 && funcs.reduce((acc, x) => acc + (x.export ? 1 : 0), 0) > 1) funcs.splice(main.index - importedFuncs.length, 1);
|
4060
4015
|
|