porffor 0.0.0-61de729 → 0.0.0-679c4ea
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -14
- package/c +0 -0
- package/c.exe +0 -0
- package/compiler/2c.js +350 -0
- package/compiler/builtins.js +6 -1
- package/compiler/codeGen.js +435 -123
- package/compiler/decompile.js +3 -3
- package/compiler/embedding.js +9 -5
- package/compiler/encoding.js +4 -2
- package/compiler/index.js +47 -5
- package/compiler/opt.js +48 -22
- package/compiler/parse.js +1 -0
- package/compiler/prototype.js +92 -29
- package/compiler/sections.js +42 -4
- package/compiler/wrap.js +12 -3
- package/cool.exe +0 -0
- package/g +0 -0
- package/g.exe +0 -0
- package/hi.c +37 -0
- package/out +0 -0
- package/out.exe +0 -0
- package/package.json +1 -1
- package/r.js +39 -0
- package/rhemyn/README.md +37 -0
- package/rhemyn/compile.js +214 -0
- package/rhemyn/parse.js +321 -0
- package/rhemyn/test/parse.js +59 -0
- package/runner/index.js +54 -40
- package/runner/info.js +37 -2
- package/runner/transform.js +2 -1
- package/tmp.c +58 -0
package/compiler/codeGen.js
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from "./wasmSpec.js";
|
2
|
-
import { signedLEB128, unsignedLEB128 } from "./encoding.js";
|
2
|
+
import { ieee754_binary64, signedLEB128, unsignedLEB128 } 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";
|
6
|
-
import { number, i32x4 } from "./embedding.js";
|
6
|
+
import { number, i32x4, enforceOneByte, enforceTwoBytes, enforceFourBytes, enforceEightBytes } from "./embedding.js";
|
7
7
|
import parse from "./parse.js";
|
8
|
+
import * as Rhemyn from "../rhemyn/compile.js";
|
8
9
|
|
9
10
|
let globals = {};
|
10
11
|
let globalInd = 0;
|
@@ -108,8 +109,8 @@ const generate = (scope, decl, global = false, name = undefined) => {
|
|
108
109
|
case 'WhileStatement':
|
109
110
|
return generateWhile(scope, decl);
|
110
111
|
|
111
|
-
|
112
|
-
return generateForOf(scope, decl);
|
112
|
+
case 'ForOfStatement':
|
113
|
+
return generateForOf(scope, decl);
|
113
114
|
|
114
115
|
case 'BreakStatement':
|
115
116
|
return generateBreak(scope, decl);
|
@@ -151,45 +152,65 @@ const generate = (scope, decl, global = false, name = undefined) => {
|
|
151
152
|
|
152
153
|
return [];
|
153
154
|
|
154
|
-
case 'TaggedTemplateExpression':
|
155
|
-
|
156
|
-
|
155
|
+
case 'TaggedTemplateExpression': {
|
156
|
+
const funcs = {
|
157
|
+
asm: str => {
|
158
|
+
let out = [];
|
157
159
|
|
158
|
-
|
159
|
-
|
160
|
+
for (const line of str.split('\n')) {
|
161
|
+
const asm = line.trim().split(';;')[0].split(' ');
|
162
|
+
if (asm[0] === '') continue; // blank
|
160
163
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
+
if (asm[0] === 'local') {
|
165
|
+
const [ name, idx, type ] = asm.slice(1);
|
166
|
+
scope.locals[name] = { idx: parseInt(idx), type: Valtype[type] };
|
167
|
+
continue;
|
168
|
+
}
|
164
169
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
}
|
170
|
+
if (asm[0] === 'returns') {
|
171
|
+
scope.returns = asm.slice(1).map(x => Valtype[x]);
|
172
|
+
continue;
|
173
|
+
}
|
170
174
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
+
if (asm[0] === 'memory') {
|
176
|
+
allocPage('asm instrinsic');
|
177
|
+
// todo: add to store/load offset insts
|
178
|
+
continue;
|
179
|
+
}
|
175
180
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
}
|
181
|
+
let inst = Opcodes[asm[0].replace('.', '_')];
|
182
|
+
if (!inst) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
183
|
+
|
184
|
+
if (!Array.isArray(inst)) inst = [ inst ];
|
185
|
+
const immediates = asm.slice(1).map(x => parseInt(x));
|
182
186
|
|
183
|
-
|
184
|
-
|
187
|
+
out.push([ ...inst, ...immediates ]);
|
188
|
+
}
|
185
189
|
|
186
|
-
|
187
|
-
|
190
|
+
return out;
|
191
|
+
},
|
188
192
|
|
189
|
-
|
193
|
+
__internal_print_type: str => {
|
194
|
+
const type = getType(scope, str) - TYPES.number;
|
195
|
+
|
196
|
+
return [
|
197
|
+
...number(type),
|
198
|
+
[ Opcodes.call, importedFuncs.print ],
|
199
|
+
|
200
|
+
// newline
|
201
|
+
...number(10),
|
202
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
203
|
+
];
|
204
|
+
}
|
190
205
|
}
|
191
206
|
|
192
|
-
|
207
|
+
const name = decl.tag.name;
|
208
|
+
// hack for inline asm
|
209
|
+
if (!funcs[name]) return todo('tagged template expressions not implemented');
|
210
|
+
|
211
|
+
const str = decl.quasi.quasis[0].value.raw;
|
212
|
+
return funcs[name](str);
|
213
|
+
}
|
193
214
|
|
194
215
|
default:
|
195
216
|
return todo(`no generation for ${decl.type}!`);
|
@@ -288,7 +309,7 @@ const generateReturn = (scope, decl) => {
|
|
288
309
|
];
|
289
310
|
}
|
290
311
|
|
291
|
-
|
312
|
+
scope.returnType = getNodeType(scope, decl.argument);
|
292
313
|
|
293
314
|
return [
|
294
315
|
...generate(scope, decl.argument),
|
@@ -309,7 +330,7 @@ const performLogicOp = (scope, op, left, right, leftType, rightType) => {
|
|
309
330
|
const checks = {
|
310
331
|
'||': falsy,
|
311
332
|
'&&': truthy,
|
312
|
-
|
333
|
+
'??': nullish
|
313
334
|
};
|
314
335
|
|
315
336
|
if (!checks[op]) return todo(`logic operator ${op} not implemented yet`);
|
@@ -336,8 +357,6 @@ const concatStrings = (scope, left, right, global, name, assign) => {
|
|
336
357
|
// todo: optimize by looking up names in arrays and using that if exists?
|
337
358
|
// todo: optimize this if using literals/known lengths?
|
338
359
|
|
339
|
-
scope.memory = true;
|
340
|
-
|
341
360
|
const rightPointer = localTmp(scope, 'concat_right_pointer', Valtype.i32);
|
342
361
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
343
362
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
@@ -472,8 +491,6 @@ const compareStrings = (scope, left, right) => {
|
|
472
491
|
// todo: optimize by looking up names in arrays and using that if exists?
|
473
492
|
// todo: optimize this if using literals/known lengths?
|
474
493
|
|
475
|
-
scope.memory = true;
|
476
|
-
|
477
494
|
const leftPointer = localTmp(scope, 'compare_left_pointer', Valtype.i32);
|
478
495
|
const leftLength = localTmp(scope, 'compare_left_length', Valtype.i32);
|
479
496
|
const rightPointer = localTmp(scope, 'compare_right_pointer', Valtype.i32);
|
@@ -575,8 +592,8 @@ const truthy = (scope, wasm, type) => {
|
|
575
592
|
// arrays are always truthy
|
576
593
|
if (type === TYPES._array) return [
|
577
594
|
...wasm,
|
578
|
-
|
579
|
-
number(1)
|
595
|
+
[ Opcodes.drop ],
|
596
|
+
...number(1)
|
580
597
|
];
|
581
598
|
|
582
599
|
if (type === TYPES.string) {
|
@@ -610,8 +627,8 @@ const falsy = (scope, wasm, type) => {
|
|
610
627
|
// arrays are always truthy
|
611
628
|
if (type === TYPES._array) return [
|
612
629
|
...wasm,
|
613
|
-
|
614
|
-
number(0)
|
630
|
+
[ Opcodes.drop ],
|
631
|
+
...number(0)
|
615
632
|
];
|
616
633
|
|
617
634
|
if (type === TYPES.string) {
|
@@ -639,6 +656,29 @@ const falsy = (scope, wasm, type) => {
|
|
639
656
|
];
|
640
657
|
};
|
641
658
|
|
659
|
+
const nullish = (scope, wasm, type) => {
|
660
|
+
// undefined
|
661
|
+
if (type === TYPES.undefined) return [
|
662
|
+
...wasm,
|
663
|
+
[ Opcodes.drop ],
|
664
|
+
...number(1)
|
665
|
+
];
|
666
|
+
|
667
|
+
// null (if object and = "0")
|
668
|
+
if (type === TYPES.object) return [
|
669
|
+
...wasm,
|
670
|
+
...Opcodes.eqz,
|
671
|
+
Opcodes.i32_from_u
|
672
|
+
];
|
673
|
+
|
674
|
+
// not
|
675
|
+
return [
|
676
|
+
...wasm,
|
677
|
+
[ Opcodes.drop ],
|
678
|
+
...number(0)
|
679
|
+
];
|
680
|
+
};
|
681
|
+
|
642
682
|
const performOp = (scope, op, left, right, leftType, rightType, _global = false, _name = '$undeclared', assign = false) => {
|
643
683
|
if (op === '||' || op === '&&' || op === '??') {
|
644
684
|
return performLogicOp(scope, op, left, right, leftType, rightType);
|
@@ -646,29 +686,44 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
646
686
|
|
647
687
|
if (codeLog && (!leftType || !rightType)) log('codegen', 'untracked type in op', op, _name, '\n' + new Error().stack.split('\n').slice(1).join('\n'));
|
648
688
|
|
649
|
-
|
650
|
-
|
689
|
+
const eqOp = ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(op);
|
690
|
+
|
691
|
+
if (leftType && rightType && (
|
692
|
+
// if strict (in)equal and known types mismatch, return false (===)/true (!==)
|
693
|
+
((op === '===' || op === '!==') && leftType !== rightType) ||
|
694
|
+
|
695
|
+
// if equality op and an operand is undefined, return false
|
696
|
+
(eqOp && leftType === TYPES.undefined ^ rightType === TYPES.undefined)
|
697
|
+
)) {
|
698
|
+
// undefined == null
|
699
|
+
if (((leftType === TYPES.undefined && rightType === TYPES.object) || (leftType === TYPES.object && rightType === TYPES.undefined)) && (op === '==' || op === '!=')) return [
|
700
|
+
...(leftType === TYPES.object ? left : right),
|
701
|
+
...Opcodes.eqz,
|
702
|
+
...(op === '!=' ? [ [ Opcodes.i32_eqz ] ] : [])
|
703
|
+
];
|
704
|
+
|
651
705
|
return [
|
652
706
|
...left,
|
653
|
-
...right,
|
654
|
-
|
655
|
-
// drop values
|
656
707
|
[ Opcodes.drop ],
|
708
|
+
|
709
|
+
...right,
|
657
710
|
[ Opcodes.drop ],
|
658
711
|
|
659
|
-
// return
|
660
|
-
...number(op === '===' ?
|
712
|
+
// return true (!=/!==) or false (else)
|
713
|
+
...number(op === '!=' || op === '!==' ? 1 : 0, Valtype.i32)
|
661
714
|
];
|
662
715
|
}
|
663
716
|
|
717
|
+
// todo: niche null hell with 0
|
718
|
+
|
664
719
|
if (leftType === TYPES.string || rightType === TYPES.string) {
|
665
720
|
if (op === '+') {
|
666
721
|
// string concat (a + b)
|
667
722
|
return concatStrings(scope, left, right, _global, _name, assign);
|
668
723
|
}
|
669
724
|
|
670
|
-
//
|
671
|
-
if (!
|
725
|
+
// not an equality op, NaN
|
726
|
+
if (!eqOp) return number(NaN);
|
672
727
|
|
673
728
|
// else leave bool ops
|
674
729
|
// todo: convert string to number if string and number/bool
|
@@ -713,21 +768,15 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
713
768
|
];
|
714
769
|
};
|
715
770
|
|
716
|
-
let binaryExpDepth = 0;
|
717
771
|
const generateBinaryExp = (scope, decl, _global, _name) => {
|
718
|
-
|
719
|
-
|
720
|
-
const out = [
|
721
|
-
...performOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right), _global, _name)
|
722
|
-
];
|
772
|
+
const out = performOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right), _global, _name);
|
723
773
|
|
724
774
|
if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
|
725
775
|
|
726
|
-
binaryExpDepth--;
|
727
776
|
return out;
|
728
777
|
};
|
729
778
|
|
730
|
-
const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes = [], globalInits, returns, returnType,
|
779
|
+
const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes = [], globalInits, returns, returnType, localNames = [], globalNames = [] }) => {
|
731
780
|
const existing = funcs.find(x => x.name === name);
|
732
781
|
if (existing) return existing;
|
733
782
|
|
@@ -763,7 +812,6 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
763
812
|
returns,
|
764
813
|
returnType: TYPES[returnType ?? 'number'],
|
765
814
|
wasm,
|
766
|
-
memory,
|
767
815
|
internal: true,
|
768
816
|
index: currentFuncIndex++
|
769
817
|
};
|
@@ -796,7 +844,8 @@ const TYPES = {
|
|
796
844
|
bigint: 0xffffffffffff7,
|
797
845
|
|
798
846
|
// these are not "typeof" types but tracked internally
|
799
|
-
_array:
|
847
|
+
_array: 0xfffffffffff0f,
|
848
|
+
_regexp: 0xfffffffffff1f
|
800
849
|
};
|
801
850
|
|
802
851
|
const TYPE_NAMES = {
|
@@ -831,6 +880,8 @@ const getType = (scope, _name) => {
|
|
831
880
|
const getNodeType = (scope, node) => {
|
832
881
|
if (node.type === 'Literal') {
|
833
882
|
if (['number', 'boolean', 'string', 'undefined', 'object', 'function', 'symbol', 'bigint'].includes(node.value)) return TYPES.number;
|
883
|
+
if (node.regex) return TYPES._regexp;
|
884
|
+
|
834
885
|
return TYPES[typeof node.value];
|
835
886
|
}
|
836
887
|
|
@@ -864,6 +915,11 @@ const getNodeType = (scope, node) => {
|
|
864
915
|
|
865
916
|
// literal.func()
|
866
917
|
if (!name && node.callee.type === 'MemberExpression') {
|
918
|
+
if (node.callee.object.regex) {
|
919
|
+
const funcName = node.callee.property.name;
|
920
|
+
return Rhemyn[funcName] ? TYPES.boolean : TYPES.undefined;
|
921
|
+
}
|
922
|
+
|
867
923
|
const baseType = getNodeType(scope, node.callee.object);
|
868
924
|
|
869
925
|
const func = node.callee.property.name;
|
@@ -907,6 +963,11 @@ const getNodeType = (scope, node) => {
|
|
907
963
|
const generateLiteral = (scope, decl, global, name) => {
|
908
964
|
if (decl.value === null) return number(NULL);
|
909
965
|
|
966
|
+
if (decl.regex) {
|
967
|
+
scope.regex[name] = decl.regex;
|
968
|
+
return number(1);
|
969
|
+
}
|
970
|
+
|
910
971
|
switch (typeof decl.value) {
|
911
972
|
case 'number':
|
912
973
|
return number(decl.value);
|
@@ -946,7 +1007,8 @@ const generateLiteral = (scope, decl, global, name) => {
|
|
946
1007
|
const countLeftover = wasm => {
|
947
1008
|
let count = 0, depth = 0;
|
948
1009
|
|
949
|
-
for (
|
1010
|
+
for (let i = 0; i < wasm.length; i++) {
|
1011
|
+
const inst = wasm[i];
|
950
1012
|
if (depth === 0 && (inst[0] === Opcodes.if || inst[0] === Opcodes.block || inst[0] === Opcodes.loop)) {
|
951
1013
|
if (inst[0] === Opcodes.if) count--;
|
952
1014
|
if (inst[1] !== Blocktype.void) count++;
|
@@ -967,6 +1029,8 @@ const countLeftover = wasm => {
|
|
967
1029
|
} else count--;
|
968
1030
|
if (func) count += func.returns.length;
|
969
1031
|
} else count--;
|
1032
|
+
|
1033
|
+
// console.log(count, decompile([ inst ]).slice(0, -1));
|
970
1034
|
}
|
971
1035
|
|
972
1036
|
return count;
|
@@ -1050,7 +1114,7 @@ const generateCall = (scope, decl, _global, _name) => {
|
|
1050
1114
|
}
|
1051
1115
|
|
1052
1116
|
let out = [];
|
1053
|
-
let protoFunc, protoName, baseType, baseName
|
1117
|
+
let protoFunc, protoName, baseType, baseName;
|
1054
1118
|
// ident.func()
|
1055
1119
|
if (name && name.startsWith('__')) {
|
1056
1120
|
const spl = name.slice(2).split('_');
|
@@ -1065,6 +1129,25 @@ const generateCall = (scope, decl, _global, _name) => {
|
|
1065
1129
|
|
1066
1130
|
// literal.func()
|
1067
1131
|
if (!name && decl.callee.type === 'MemberExpression') {
|
1132
|
+
// megahack for /regex/.func()
|
1133
|
+
if (decl.callee.object.regex) {
|
1134
|
+
const funcName = decl.callee.property.name;
|
1135
|
+
const func = Rhemyn[funcName](decl.callee.object.regex.pattern, currentFuncIndex++);
|
1136
|
+
|
1137
|
+
funcIndex[func.name] = func.index;
|
1138
|
+
funcs.push(func);
|
1139
|
+
|
1140
|
+
return [
|
1141
|
+
// make string arg
|
1142
|
+
...generate(scope, decl.arguments[0]),
|
1143
|
+
|
1144
|
+
// call regex func
|
1145
|
+
Opcodes.i32_to_u,
|
1146
|
+
[ Opcodes.call, func.index ],
|
1147
|
+
Opcodes.i32_from
|
1148
|
+
];
|
1149
|
+
}
|
1150
|
+
|
1068
1151
|
baseType = getNodeType(scope, decl.callee.object);
|
1069
1152
|
|
1070
1153
|
const func = decl.callee.property.name;
|
@@ -1073,11 +1156,36 @@ const generateCall = (scope, decl, _global, _name) => {
|
|
1073
1156
|
|
1074
1157
|
out = generate(scope, decl.callee.object);
|
1075
1158
|
out.push([ Opcodes.drop ]);
|
1159
|
+
|
1160
|
+
baseName = [...arrays.keys()].pop();
|
1076
1161
|
}
|
1077
1162
|
|
1078
|
-
if (
|
1079
|
-
|
1163
|
+
if (protoName && baseType === TYPES.string && Rhemyn[protoName]) {
|
1164
|
+
const func = Rhemyn[protoName](decl.arguments[0].regex.pattern, currentFuncIndex++);
|
1165
|
+
|
1166
|
+
funcIndex[func.name] = func.index;
|
1167
|
+
funcs.push(func);
|
1080
1168
|
|
1169
|
+
const pointer = arrays.get(baseName);
|
1170
|
+
const [ local, isGlobal ] = lookupName(scope, baseName);
|
1171
|
+
|
1172
|
+
return [
|
1173
|
+
...out,
|
1174
|
+
|
1175
|
+
...(pointer == null ? [
|
1176
|
+
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
1177
|
+
Opcodes.i32_to_u,
|
1178
|
+
] : [
|
1179
|
+
...number(pointer, Valtype.i32)
|
1180
|
+
]),
|
1181
|
+
|
1182
|
+
// call regex func
|
1183
|
+
[ Opcodes.call, func.index ],
|
1184
|
+
Opcodes.i32_from
|
1185
|
+
];
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
if (protoFunc) {
|
1081
1189
|
let pointer = arrays.get(baseName);
|
1082
1190
|
|
1083
1191
|
if (pointer == null) {
|
@@ -1085,7 +1193,7 @@ const generateCall = (scope, decl, _global, _name) => {
|
|
1085
1193
|
if (codeLog) log('codegen', 'cloning unknown dynamic pointer');
|
1086
1194
|
|
1087
1195
|
// register array
|
1088
|
-
|
1196
|
+
0, [ , pointer ] = makeArray(scope, {
|
1089
1197
|
rawElements: new Array(0)
|
1090
1198
|
}, _global, baseName, true, baseType === TYPES.string ? 'i16' : valtype);
|
1091
1199
|
|
@@ -1109,24 +1217,34 @@ const generateCall = (scope, decl, _global, _name) => {
|
|
1109
1217
|
// use local for cached i32 length as commonly used
|
1110
1218
|
let lengthLocal = localTmp(scope, '__proto_length_cache', Valtype.i32);
|
1111
1219
|
|
1220
|
+
let lengthI32CacheUsed = false;
|
1221
|
+
|
1222
|
+
const protoOut = protoFunc(pointer, {
|
1223
|
+
getCachedI32: () => {
|
1224
|
+
lengthI32CacheUsed = true;
|
1225
|
+
return [ [ Opcodes.local_get, lengthLocal ] ]
|
1226
|
+
},
|
1227
|
+
setCachedI32: () => [ [ Opcodes.local_set, lengthLocal ] ],
|
1228
|
+
get: () => arrayUtil.getLength(pointer),
|
1229
|
+
getI32: () => arrayUtil.getLengthI32(pointer),
|
1230
|
+
set: value => arrayUtil.setLength(pointer, value),
|
1231
|
+
setI32: value => arrayUtil.setLengthI32(pointer, value)
|
1232
|
+
}, generate(scope, decl.arguments[0] ?? DEFAULT_VALUE), protoLocal, (length, itemType) => {
|
1233
|
+
return makeArray(scope, {
|
1234
|
+
rawElements: new Array(length)
|
1235
|
+
}, _global, _name, true, itemType);
|
1236
|
+
});
|
1237
|
+
|
1112
1238
|
return [
|
1113
1239
|
...out,
|
1114
1240
|
|
1115
|
-
...
|
1116
|
-
|
1241
|
+
...(!lengthI32CacheUsed ? [] : [
|
1242
|
+
...arrayUtil.getLengthI32(pointer),
|
1243
|
+
[ Opcodes.local_set, lengthLocal ],
|
1244
|
+
]),
|
1117
1245
|
|
1118
1246
|
[ Opcodes.block, valtypeBinary ],
|
1119
|
-
...
|
1120
|
-
cachedI32: [ [ Opcodes.local_get, lengthLocal ] ],
|
1121
|
-
get: arrayUtil.getLength(pointer),
|
1122
|
-
getI32: arrayUtil.getLengthI32(pointer),
|
1123
|
-
set: value => arrayUtil.setLength(pointer, value),
|
1124
|
-
setI32: value => arrayUtil.setLengthI32(pointer, value)
|
1125
|
-
}, generate(scope, decl.arguments[0] ?? DEFAULT_VALUE), protoLocal, (length, itemType) => {
|
1126
|
-
return makeArray(scope, {
|
1127
|
-
rawElements: new Array(length)
|
1128
|
-
}, _global, _name, true, itemType);
|
1129
|
-
}),
|
1247
|
+
...protoOut,
|
1130
1248
|
[ Opcodes.end ]
|
1131
1249
|
];
|
1132
1250
|
}
|
@@ -1183,11 +1301,10 @@ const generateCall = (scope, decl, _global, _name) => {
|
|
1183
1301
|
args = args.slice(0, func.params.length);
|
1184
1302
|
}
|
1185
1303
|
|
1186
|
-
if (func && func.memory) scope.memory = true;
|
1187
1304
|
if (func && func.throws) scope.throws = true;
|
1188
1305
|
|
1189
1306
|
for (const arg of args) {
|
1190
|
-
out.
|
1307
|
+
out = out.concat(generate(scope, arg));
|
1191
1308
|
}
|
1192
1309
|
|
1193
1310
|
out.push([ Opcodes.call, idx ]);
|
@@ -1198,7 +1315,7 @@ const generateCall = (scope, decl, _global, _name) => {
|
|
1198
1315
|
const generateNew = (scope, decl, _global, _name) => {
|
1199
1316
|
// hack: basically treat this as a normal call for builtins for now
|
1200
1317
|
const name = mapName(decl.callee.name);
|
1201
|
-
if (internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
|
1318
|
+
if (internalConstrs[name] && !internalConstrs[name].notConstr) return internalConstrs[name].generate(scope, decl, _global, _name);
|
1202
1319
|
if (!builtinFuncs[name]) return todo(`new statement is not supported yet`); // return todo(`new statement is not supported yet (new ${unhackName(name)})`);
|
1203
1320
|
|
1204
1321
|
return generateCall(scope, decl, _global, _name);
|
@@ -1307,8 +1424,6 @@ const generateAssign = (scope, decl) => {
|
|
1307
1424
|
const name = decl.left.object.name;
|
1308
1425
|
const pointer = arrays.get(name);
|
1309
1426
|
|
1310
|
-
scope.memory = true;
|
1311
|
-
|
1312
1427
|
const aotPointer = pointer != null;
|
1313
1428
|
|
1314
1429
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
@@ -1329,13 +1444,60 @@ const generateAssign = (scope, decl) => {
|
|
1329
1444
|
];
|
1330
1445
|
}
|
1331
1446
|
|
1447
|
+
const op = decl.operator.slice(0, -1) || '=';
|
1448
|
+
|
1449
|
+
// arr[i] | str[i]
|
1450
|
+
if (decl.left.type === 'MemberExpression' && decl.left.computed) {
|
1451
|
+
const name = decl.left.object.name;
|
1452
|
+
const pointer = arrays.get(name);
|
1453
|
+
|
1454
|
+
const aotPointer = pointer != null;
|
1455
|
+
|
1456
|
+
const newValueTmp = localTmp(scope, '__member_setter_val_tmp');
|
1457
|
+
const pointerTmp = op === '=' ? -1 : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
1458
|
+
|
1459
|
+
const parentType = getNodeType(scope, decl.left.object);
|
1460
|
+
|
1461
|
+
return [
|
1462
|
+
...(aotPointer ? [] : [
|
1463
|
+
...generate(scope, decl.left.object),
|
1464
|
+
Opcodes.i32_to_u
|
1465
|
+
]),
|
1466
|
+
|
1467
|
+
// get index as valtype
|
1468
|
+
...generate(scope, decl.left.property),
|
1469
|
+
|
1470
|
+
// convert to i32 and turn into byte offset by * valtypeSize (4 for i32, 8 for i64/f64)
|
1471
|
+
Opcodes.i32_to_u,
|
1472
|
+
...number(ValtypeSize[valtype], Valtype.i32),
|
1473
|
+
[ Opcodes.i32_mul ],
|
1474
|
+
...(aotPointer ? [] : [ [ Opcodes.i32_add ] ]),
|
1475
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
1476
|
+
|
1477
|
+
...(op === '=' ? generate(scope, decl.right, false, name) : performOp(scope, op, [
|
1478
|
+
[ Opcodes.local_get, pointerTmp ],
|
1479
|
+
[ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
1480
|
+
], generate(scope, decl.right), parentType === TYPES._array ? TYPES.number : TYPES.string, getNodeType(scope, decl.right), false, name, true)),
|
1481
|
+
[ Opcodes.local_tee, newValueTmp ],
|
1482
|
+
|
1483
|
+
...(parentType === TYPES._array ? [
|
1484
|
+
[ Opcodes.store, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
1485
|
+
] : [
|
1486
|
+
Opcodes.i32_to_u,
|
1487
|
+
[ StoreOps.i16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ]
|
1488
|
+
]),
|
1489
|
+
|
1490
|
+
[ Opcodes.local_get, newValueTmp ]
|
1491
|
+
];
|
1492
|
+
}
|
1493
|
+
|
1332
1494
|
const [ local, isGlobal ] = lookupName(scope, name);
|
1333
1495
|
|
1334
1496
|
if (local === undefined) {
|
1335
1497
|
// todo: this should be a devtools/repl/??? only thing
|
1336
1498
|
|
1337
1499
|
// only allow = for this
|
1338
|
-
if (
|
1500
|
+
if (op !== '=') return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`);
|
1339
1501
|
|
1340
1502
|
if (builtinVars[name]) {
|
1341
1503
|
// just return rhs (eg `NaN = 2`)
|
@@ -1349,8 +1511,10 @@ const generateAssign = (scope, decl) => {
|
|
1349
1511
|
];
|
1350
1512
|
}
|
1351
1513
|
|
1352
|
-
|
1353
|
-
|
1514
|
+
typeStates[name] = getNodeType(scope, decl.right);
|
1515
|
+
|
1516
|
+
if (op === '=') {
|
1517
|
+
// typeStates[name] = getNodeType(scope, decl.right);
|
1354
1518
|
|
1355
1519
|
return [
|
1356
1520
|
...generate(scope, decl.right, isGlobal, name),
|
@@ -1359,8 +1523,26 @@ const generateAssign = (scope, decl) => {
|
|
1359
1523
|
];
|
1360
1524
|
}
|
1361
1525
|
|
1526
|
+
if (op === '||' || op === '&&' || op === '??') {
|
1527
|
+
// todo: is this needed?
|
1528
|
+
// for logical assignment ops, it is not left @= right ~= left = left @ right
|
1529
|
+
// instead, left @ (left = right)
|
1530
|
+
// eg, x &&= y ~= x && (x = y)
|
1531
|
+
|
1532
|
+
return [
|
1533
|
+
...performOp(scope, op, [
|
1534
|
+
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ]
|
1535
|
+
], [
|
1536
|
+
...generate(scope, decl.right),
|
1537
|
+
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
1538
|
+
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ]
|
1539
|
+
], getType(scope, name), getNodeType(scope, decl.right), isGlobal, name, true),
|
1540
|
+
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ]
|
1541
|
+
];
|
1542
|
+
}
|
1543
|
+
|
1362
1544
|
return [
|
1363
|
-
...performOp(scope,
|
1545
|
+
...performOp(scope, op, [ [ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ] ], generate(scope, decl.right), getType(scope, name), getNodeType(scope, decl.right), isGlobal, name, true),
|
1364
1546
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
1365
1547
|
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ]
|
1366
1548
|
];
|
@@ -1390,10 +1572,11 @@ const generateUnary = (scope, decl) => {
|
|
1390
1572
|
return falsy(scope, generate(scope, decl.argument), getNodeType(scope, decl.argument));
|
1391
1573
|
|
1392
1574
|
case '~':
|
1575
|
+
// todo: does not handle Infinity properly (should convert to 0) (but opt const converting saves us sometimes)
|
1393
1576
|
return [
|
1394
1577
|
...generate(scope, decl.argument),
|
1395
1578
|
Opcodes.i32_to,
|
1396
|
-
[ Opcodes.i32_const, signedLEB128(-1) ],
|
1579
|
+
[ Opcodes.i32_const, ...signedLEB128(-1) ],
|
1397
1580
|
[ Opcodes.i32_xor ],
|
1398
1581
|
Opcodes.i32_from
|
1399
1582
|
];
|
@@ -1474,7 +1657,7 @@ const generateUpdate = (scope, decl) => {
|
|
1474
1657
|
};
|
1475
1658
|
|
1476
1659
|
const generateIf = (scope, decl) => {
|
1477
|
-
const out = truthy(scope, generate(scope, decl.test), decl.test);
|
1660
|
+
const out = truthy(scope, generate(scope, decl.test), getNodeType(scope, decl.test));
|
1478
1661
|
|
1479
1662
|
out.push(Opcodes.i32_to, [ Opcodes.if, Blocktype.void ]);
|
1480
1663
|
depth.push('if');
|
@@ -1567,18 +1750,106 @@ const generateWhile = (scope, decl) => {
|
|
1567
1750
|
const generateForOf = (scope, decl) => {
|
1568
1751
|
const out = [];
|
1569
1752
|
|
1753
|
+
const rightType = getNodeType(scope, decl.right);
|
1754
|
+
const valtypeSize = rightType === TYPES._array ? ValtypeSize[valtype] : ValtypeSize.i16; // presume array (:()
|
1755
|
+
|
1756
|
+
// todo: for of inside for of might fuck up?
|
1757
|
+
const pointer = localTmp(scope, 'forof_base_pointer', Valtype.i32);
|
1758
|
+
const length = localTmp(scope, 'forof_length', Valtype.i32);
|
1759
|
+
const counter = localTmp(scope, 'forof_counter', Valtype.i32);
|
1760
|
+
|
1761
|
+
out.push(
|
1762
|
+
// set pointer as right
|
1763
|
+
...generate(scope, decl.right),
|
1764
|
+
Opcodes.i32_to_u,
|
1765
|
+
[ Opcodes.local_set, pointer ],
|
1766
|
+
|
1767
|
+
// get length
|
1768
|
+
[ Opcodes.local_get, pointer ],
|
1769
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
1770
|
+
[ Opcodes.local_set, length ]
|
1771
|
+
);
|
1772
|
+
|
1570
1773
|
out.push([ Opcodes.loop, Blocktype.void ]);
|
1571
|
-
depth.push('
|
1774
|
+
depth.push('forof');
|
1572
1775
|
|
1573
|
-
|
1574
|
-
|
1575
|
-
depth.push('if');
|
1776
|
+
// setup local for left
|
1777
|
+
generate(scope, decl.left);
|
1576
1778
|
|
1577
|
-
|
1779
|
+
const leftName = decl.left.declarations[0].id.name;
|
1578
1780
|
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1781
|
+
// set type for local
|
1782
|
+
typeStates[leftName] = rightType === TYPES._array ? TYPES.number : TYPES.string;
|
1783
|
+
|
1784
|
+
const [ local, isGlobal ] = lookupName(scope, leftName);
|
1785
|
+
|
1786
|
+
if (rightType === TYPES._array) { // array
|
1787
|
+
out.push(
|
1788
|
+
[ Opcodes.local_get, pointer ],
|
1789
|
+
[ Opcodes.load, Math.log2(valtypeSize) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
|
1790
|
+
);
|
1791
|
+
} else { // string
|
1792
|
+
const [ newOut, newPointer ] = makeArray(scope, {
|
1793
|
+
rawElements: new Array(1)
|
1794
|
+
}, isGlobal, leftName, true, 'i16');
|
1795
|
+
|
1796
|
+
out.push(
|
1797
|
+
// setup new/out array
|
1798
|
+
...newOut,
|
1799
|
+
[ Opcodes.drop ],
|
1800
|
+
|
1801
|
+
...number(0, Valtype.i32), // base 0 for store after
|
1802
|
+
|
1803
|
+
// load current string ind {arg}
|
1804
|
+
[ Opcodes.local_get, pointer ],
|
1805
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
|
1806
|
+
|
1807
|
+
// store to new string ind 0
|
1808
|
+
[ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
1809
|
+
|
1810
|
+
// return new string (page)
|
1811
|
+
...number(newPointer)
|
1812
|
+
);
|
1813
|
+
}
|
1814
|
+
|
1815
|
+
// set left value
|
1816
|
+
out.push([ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ]);
|
1817
|
+
|
1818
|
+
out.push(
|
1819
|
+
[ Opcodes.block, Blocktype.void ],
|
1820
|
+
[ Opcodes.block, Blocktype.void ]
|
1821
|
+
);
|
1822
|
+
depth.push('block');
|
1823
|
+
depth.push('block');
|
1824
|
+
|
1825
|
+
out.push(
|
1826
|
+
...generate(scope, decl.body),
|
1827
|
+
[ Opcodes.end ]
|
1828
|
+
);
|
1829
|
+
depth.pop();
|
1830
|
+
|
1831
|
+
out.push(
|
1832
|
+
// increment iter pointer by valtype size
|
1833
|
+
[ Opcodes.local_get, pointer ],
|
1834
|
+
...number(valtypeSize, Valtype.i32),
|
1835
|
+
[ Opcodes.i32_add ],
|
1836
|
+
[ Opcodes.local_set, pointer ],
|
1837
|
+
|
1838
|
+
// increment counter by 1
|
1839
|
+
[ Opcodes.local_get, counter ],
|
1840
|
+
...number(1, Valtype.i32),
|
1841
|
+
[ Opcodes.i32_add ],
|
1842
|
+
[ Opcodes.local_tee, counter ],
|
1843
|
+
|
1844
|
+
// loop if counter != length
|
1845
|
+
[ Opcodes.local_get, length ],
|
1846
|
+
[ Opcodes.i32_ne ],
|
1847
|
+
[ Opcodes.br_if, 1 ],
|
1848
|
+
|
1849
|
+
[ Opcodes.end ], [ Opcodes.end ]
|
1850
|
+
);
|
1851
|
+
depth.pop();
|
1852
|
+
depth.pop();
|
1582
1853
|
|
1583
1854
|
return out;
|
1584
1855
|
};
|
@@ -1669,19 +1940,19 @@ const generateAssignPat = (scope, decl) => {
|
|
1669
1940
|
};
|
1670
1941
|
|
1671
1942
|
let pages = new Map();
|
1672
|
-
const allocPage = reason => {
|
1673
|
-
if (pages.has(reason)) return pages.get(reason);
|
1943
|
+
const allocPage = (reason, type) => {
|
1944
|
+
if (pages.has(reason)) return pages.get(reason).ind;
|
1674
1945
|
|
1675
|
-
|
1676
|
-
pages.set(reason, ind);
|
1946
|
+
const ind = pages.size;
|
1947
|
+
pages.set(reason, { ind, type });
|
1677
1948
|
|
1678
|
-
if (allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason}`);
|
1949
|
+
if (allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
|
1679
1950
|
|
1680
1951
|
return ind;
|
1681
1952
|
};
|
1682
1953
|
|
1683
1954
|
const freePage = reason => {
|
1684
|
-
|
1955
|
+
const { ind } = pages.get(reason);
|
1685
1956
|
pages.delete(reason);
|
1686
1957
|
|
1687
1958
|
if (allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
|
@@ -1698,7 +1969,7 @@ const itemTypeToValtype = {
|
|
1698
1969
|
i16: 'i32'
|
1699
1970
|
};
|
1700
1971
|
|
1701
|
-
const
|
1972
|
+
const StoreOps = {
|
1702
1973
|
i32: Opcodes.i32_store,
|
1703
1974
|
i64: Opcodes.i64_store,
|
1704
1975
|
f64: Opcodes.f64_store,
|
@@ -1707,13 +1978,28 @@ const storeOps = {
|
|
1707
1978
|
i16: Opcodes.i32_store16
|
1708
1979
|
};
|
1709
1980
|
|
1981
|
+
let data = [];
|
1982
|
+
|
1983
|
+
const compileBytes = (val, itemType, signed = true) => {
|
1984
|
+
switch (itemType) {
|
1985
|
+
case 'i8': return enforceOneByte(unsignedLEB128(val));
|
1986
|
+
case 'i16': return enforceTwoBytes(unsignedLEB128(val));
|
1987
|
+
case 'i32': return enforceFourBytes(signedLEB128(val));
|
1988
|
+
case 'i64': return enforceEightBytes(signedLEB128(val));
|
1989
|
+
case 'f64': return enforceEightBytes(ieee754_binary64(val));
|
1990
|
+
}
|
1991
|
+
};
|
1992
|
+
|
1710
1993
|
const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false, itemType = valtype) => {
|
1711
1994
|
const out = [];
|
1712
1995
|
|
1996
|
+
let firstAssign = false;
|
1713
1997
|
if (!arrays.has(name) || name === '$undeclared') {
|
1998
|
+
firstAssign = true;
|
1999
|
+
|
1714
2000
|
// todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
|
1715
2001
|
const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
|
1716
|
-
arrays.set(name, allocPage(`${itemType === 'i16' ? 'string' : 'array'}: ${uniqueName}
|
2002
|
+
arrays.set(name, allocPage(`${itemType === 'i16' ? 'string' : 'array'}: ${uniqueName}`, itemType) * pageSize);
|
1717
2003
|
}
|
1718
2004
|
|
1719
2005
|
const pointer = arrays.get(name);
|
@@ -1721,8 +2007,29 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
1721
2007
|
const useRawElements = !!decl.rawElements;
|
1722
2008
|
const elements = useRawElements ? decl.rawElements : decl.elements;
|
1723
2009
|
|
2010
|
+
const valtype = itemTypeToValtype[itemType];
|
1724
2011
|
const length = elements.length;
|
1725
2012
|
|
2013
|
+
if (firstAssign && useRawElements) {
|
2014
|
+
let bytes = compileBytes(length, 'i32');
|
2015
|
+
|
2016
|
+
if (!initEmpty) for (let i = 0; i < length; i++) {
|
2017
|
+
if (elements[i] == null) continue;
|
2018
|
+
|
2019
|
+
bytes.push(...compileBytes(elements[i], itemType));
|
2020
|
+
}
|
2021
|
+
|
2022
|
+
data.push({
|
2023
|
+
offset: pointer,
|
2024
|
+
bytes
|
2025
|
+
});
|
2026
|
+
|
2027
|
+
// local value as pointer
|
2028
|
+
out.push(...number(pointer));
|
2029
|
+
|
2030
|
+
return [ out, pointer ];
|
2031
|
+
}
|
2032
|
+
|
1726
2033
|
// store length as 0th array
|
1727
2034
|
out.push(
|
1728
2035
|
...number(0, Valtype.i32),
|
@@ -1730,8 +2037,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
1730
2037
|
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(pointer) ]
|
1731
2038
|
);
|
1732
2039
|
|
1733
|
-
const storeOp =
|
1734
|
-
const valtype = itemTypeToValtype[itemType];
|
2040
|
+
const storeOp = StoreOps[itemType];
|
1735
2041
|
|
1736
2042
|
if (!initEmpty) for (let i = 0; i < length; i++) {
|
1737
2043
|
if (elements[i] == null) continue;
|
@@ -1746,8 +2052,6 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
1746
2052
|
// local value as pointer
|
1747
2053
|
out.push(...number(pointer));
|
1748
2054
|
|
1749
|
-
scope.memory = true;
|
1750
|
-
|
1751
2055
|
return [ out, pointer ];
|
1752
2056
|
};
|
1753
2057
|
|
@@ -1766,8 +2070,6 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
1766
2070
|
const name = decl.object.name;
|
1767
2071
|
const pointer = arrays.get(name);
|
1768
2072
|
|
1769
|
-
scope.memory = true;
|
1770
|
-
|
1771
2073
|
const aotPointer = pointer != null;
|
1772
2074
|
|
1773
2075
|
return [
|
@@ -1787,8 +2089,6 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
1787
2089
|
const name = decl.object.name;
|
1788
2090
|
const pointer = arrays.get(name);
|
1789
2091
|
|
1790
|
-
scope.memory = true;
|
1791
|
-
|
1792
2092
|
const aotPointer = pointer != null;
|
1793
2093
|
|
1794
2094
|
if (type === TYPES._array) {
|
@@ -1898,7 +2198,7 @@ const generateFunc = (scope, decl) => {
|
|
1898
2198
|
locals: {},
|
1899
2199
|
localInd: 0,
|
1900
2200
|
returns: [ valtypeBinary ],
|
1901
|
-
|
2201
|
+
returnType: null,
|
1902
2202
|
throws: false,
|
1903
2203
|
name
|
1904
2204
|
};
|
@@ -1924,7 +2224,6 @@ const generateFunc = (scope, decl) => {
|
|
1924
2224
|
returns: innerScope.returns,
|
1925
2225
|
returnType: innerScope.returnType,
|
1926
2226
|
locals: innerScope.locals,
|
1927
|
-
memory: innerScope.memory,
|
1928
2227
|
throws: innerScope.throws,
|
1929
2228
|
index: currentFuncIndex++
|
1930
2229
|
};
|
@@ -1939,6 +2238,8 @@ const generateFunc = (scope, decl) => {
|
|
1939
2238
|
|
1940
2239
|
if (name !== 'main' && func.returns.length !== 0 && wasm[wasm.length - 1]?.[0] !== Opcodes.return && countLeftover(wasm) === 0) {
|
1941
2240
|
wasm.push(...number(0), [ Opcodes.return ]);
|
2241
|
+
|
2242
|
+
if (func.returnType === null) func.returnType = TYPES.undefined;
|
1942
2243
|
}
|
1943
2244
|
|
1944
2245
|
// change v128 params into many <type> (i32x4 -> i32/etc) instead as unsupported param valtype
|
@@ -1949,9 +2250,7 @@ const generateFunc = (scope, decl) => {
|
|
1949
2250
|
if (local.type === Valtype.v128) {
|
1950
2251
|
vecParams++;
|
1951
2252
|
|
1952
|
-
/*
|
1953
|
-
|
1954
|
-
wasm.unshift( // add v128 load for param
|
2253
|
+
/* wasm.unshift( // add v128 load for param
|
1955
2254
|
[ Opcodes.i32_const, 0 ],
|
1956
2255
|
[ ...Opcodes.v128_load, 0, i * 16 ],
|
1957
2256
|
[ Opcodes.local_set, local.idx ]
|
@@ -2062,10 +2361,10 @@ const generateFunc = (scope, decl) => {
|
|
2062
2361
|
};
|
2063
2362
|
|
2064
2363
|
const generateCode = (scope, decl) => {
|
2065
|
-
|
2364
|
+
let out = [];
|
2066
2365
|
|
2067
2366
|
for (const x of decl.body) {
|
2068
|
-
out.
|
2367
|
+
out = out.concat(generate(scope, x));
|
2069
2368
|
}
|
2070
2369
|
|
2071
2370
|
return out;
|
@@ -2101,6 +2400,18 @@ const internalConstrs = {
|
|
2101
2400
|
];
|
2102
2401
|
},
|
2103
2402
|
type: TYPES._array
|
2403
|
+
},
|
2404
|
+
|
2405
|
+
__Array_of: {
|
2406
|
+
// this is not a constructor but best fits internal structure here
|
2407
|
+
generate: (scope, decl, global, name) => {
|
2408
|
+
// Array.of(i0, i1, ...)
|
2409
|
+
return generateArray(scope, {
|
2410
|
+
elements: decl.arguments
|
2411
|
+
}, global, name);
|
2412
|
+
},
|
2413
|
+
type: TYPES._array,
|
2414
|
+
notConstr: true
|
2104
2415
|
}
|
2105
2416
|
};
|
2106
2417
|
|
@@ -2115,6 +2426,7 @@ export default program => {
|
|
2115
2426
|
typeStates = {};
|
2116
2427
|
arrays = new Map();
|
2117
2428
|
pages = new Map();
|
2429
|
+
data = [];
|
2118
2430
|
currentFuncIndex = importedFuncs.length;
|
2119
2431
|
|
2120
2432
|
globalThis.valtype = 'f64';
|
@@ -2191,5 +2503,5 @@ export default program => {
|
|
2191
2503
|
// if blank main func and other exports, remove it
|
2192
2504
|
if (main.wasm.length === 0 && funcs.reduce((acc, x) => acc + (x.export ? 1 : 0), 0) > 1) funcs.splice(funcs.length - 1, 1);
|
2193
2505
|
|
2194
|
-
return { funcs, globals, tags, exceptions, pages };
|
2506
|
+
return { funcs, globals, tags, exceptions, pages, data };
|
2195
2507
|
};
|