porffor 0.16.0-688a50c13 → 0.16.0-7339fdd79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -17
- package/compiler/2c.js +75 -15
- package/compiler/allocators.js +128 -0
- package/compiler/assemble.js +7 -1
- package/compiler/builtins/array.ts +72 -5
- package/compiler/builtins/date.ts +2 -27
- package/compiler/builtins/number.ts +10 -21
- package/compiler/builtins/porffor.d.ts +7 -0
- package/compiler/builtins/set.ts +1 -2
- package/compiler/builtins/z_ecma262.ts +62 -0
- package/compiler/codegen.js +116 -74
- package/compiler/generated_builtins.js +100 -62
- package/compiler/index.js +15 -1
- package/compiler/opt.js +1 -1
- package/compiler/parse.js +0 -6
- package/compiler/pgo.js +5 -0
- package/compiler/precompile.js +1 -1
- package/compiler/prefs.js +1 -2
- package/compiler/wasmSpec.js +2 -2
- package/compiler/wrap.js +16 -15
- package/package.json +1 -1
- package/runner/index.js +5 -0
- package/a.txt +0 -457
- package/b.txt +0 -457
- package/compiler/allocators/grow.js +0 -26
- package/compiler/allocators/index.js +0 -10
- package/compiler/allocators/static.js +0 -42
- package/no_pgo.txt +0 -923
- package/pgo.txt +0 -916
@@ -0,0 +1,62 @@
|
|
1
|
+
// general widely used ecma262/spec functions
|
2
|
+
|
3
|
+
// 7.1.5 ToIntegerOrInfinity (argument)
|
4
|
+
// https://tc39.es/ecma262/#sec-tointegerorinfinity
|
5
|
+
export const __ecma262_ToIntegerOrInfinity = (argument: unknown): number => {
|
6
|
+
// 1. Let number be ? ToNumber(argument).
|
7
|
+
let number: number = Number(argument);
|
8
|
+
|
9
|
+
// 2. If number is one of NaN, +0𝔽, or -0𝔽, return 0.
|
10
|
+
if (Number.isNaN(number)) return 0;
|
11
|
+
|
12
|
+
// 3. If number is +∞𝔽, return +∞.
|
13
|
+
// 4. If number is -∞𝔽, return -∞.
|
14
|
+
if (!Number.isFinite(number)) return number;
|
15
|
+
|
16
|
+
// 5. Return truncate(ℝ(number)).
|
17
|
+
number = Math.trunc(number);
|
18
|
+
|
19
|
+
// return 0 for -0
|
20
|
+
if (number == 0) return 0;
|
21
|
+
return number;
|
22
|
+
};
|
23
|
+
|
24
|
+
// todo: support non-bytestring properly
|
25
|
+
// 7.1.17 ToString (argument)
|
26
|
+
// https://tc39.es/ecma262/#sec-tostring
|
27
|
+
export const __ecma262_ToString = (argument: unknown): bytestring => {
|
28
|
+
let out: bytestring = '';
|
29
|
+
const type: i32 = Porffor.rawType(argument);
|
30
|
+
|
31
|
+
// 1. If argument is a String, return argument.
|
32
|
+
if (Porffor.fastOr(
|
33
|
+
type == Porffor.TYPES.string,
|
34
|
+
type == Porffor.TYPES.bytestring)) return argument;
|
35
|
+
|
36
|
+
// 2. If argument is a Symbol, throw a TypeError exception.
|
37
|
+
if (type == Porffor.TYPES.symbol) throw new TypeError('Cannot convert a Symbol value to a string');
|
38
|
+
|
39
|
+
// 3. If argument is undefined, return "undefined".
|
40
|
+
if (type == Porffor.TYPES.undefined) return out = 'undefined';
|
41
|
+
|
42
|
+
// 4. If argument is null, return "null".
|
43
|
+
if (Porffor.fastAnd(
|
44
|
+
type == Porffor.TYPES.object,
|
45
|
+
argument == 0)) return out = 'null';
|
46
|
+
|
47
|
+
if (type == Porffor.TYPES.boolean) {
|
48
|
+
// 5. If argument is true, return "true".
|
49
|
+
if (argument == true) return out = 'true';
|
50
|
+
|
51
|
+
// 6. If argument is false, return "false".
|
52
|
+
return out = 'false';
|
53
|
+
}
|
54
|
+
|
55
|
+
// 7. If argument is a Number, return Number::toString(argument, 10).
|
56
|
+
// 8. If argument is a BigInt, return BigInt::toString(argument, 10).
|
57
|
+
// 9. Assert: argument is an Object.
|
58
|
+
// 10. Let primValue be ? ToPrimitive(argument, string).
|
59
|
+
// 11. Assert: primValue is not an Object.
|
60
|
+
// 12. Return ? ToString(primValue).
|
61
|
+
return argument.toString();
|
62
|
+
};
|
package/compiler/codegen.js
CHANGED
@@ -9,7 +9,7 @@ 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
|
12
|
+
import makeAllocator from './allocators.js';
|
13
13
|
|
14
14
|
let globals = {};
|
15
15
|
let tags = [];
|
@@ -33,11 +33,6 @@ const todo = (scope, msg, expectsValue = undefined) => {
|
|
33
33
|
|
34
34
|
case 'runtime':
|
35
35
|
return internalThrow(scope, 'TodoError', msg, expectsValue);
|
36
|
-
|
37
|
-
// return [
|
38
|
-
// ...debug(`todo! ${msg}`),
|
39
|
-
// [ Opcodes.unreachable ]
|
40
|
-
// ];
|
41
36
|
}
|
42
37
|
};
|
43
38
|
|
@@ -431,9 +426,9 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
431
426
|
const leftPointer = localTmp(scope, 'concat_left_pointer', Valtype.i32);
|
432
427
|
|
433
428
|
// alloc/assign array
|
434
|
-
const [ , pointer ] = makeArray(scope, {
|
429
|
+
const [ out, pointer ] = makeArray(scope, {
|
435
430
|
rawElements: new Array(0)
|
436
|
-
}, global, name, true, 'i16', true);
|
431
|
+
}, assign ? false : global, assign ? undefined : name, true, 'i16', true);
|
437
432
|
|
438
433
|
return [
|
439
434
|
// setup left
|
@@ -447,7 +442,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
447
442
|
[ Opcodes.local_set, rightPointer ],
|
448
443
|
|
449
444
|
// calculate length
|
450
|
-
...
|
445
|
+
...out,
|
451
446
|
|
452
447
|
[ Opcodes.local_get, leftPointer ],
|
453
448
|
[ Opcodes.i32_load, 0, ...unsignedLEB128(0) ],
|
@@ -963,12 +958,9 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
963
958
|
[ Opcodes.end ],
|
964
959
|
]));
|
965
960
|
|
966
|
-
//
|
967
|
-
|
968
|
-
|
969
|
-
// endOut.push(stringOnly([ Opcodes.end ]));
|
970
|
-
endOut.unshift(stringOnly([ Opcodes.end ]));
|
971
|
-
// }
|
961
|
+
// add a surrounding block
|
962
|
+
startOut.push(stringOnly([ Opcodes.block, Valtype.i32 ]));
|
963
|
+
endOut.unshift(stringOnly([ Opcodes.end ]));
|
972
964
|
}
|
973
965
|
|
974
966
|
return finalize([
|
@@ -1003,7 +995,7 @@ const asmFuncToAsm = (func, scope) => {
|
|
1003
995
|
});
|
1004
996
|
};
|
1005
997
|
|
1006
|
-
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 }) => {
|
1007
999
|
const existing = funcs.find(x => x.name === name);
|
1008
1000
|
if (existing) return existing;
|
1009
1001
|
|
@@ -1017,7 +1009,7 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1017
1009
|
|
1018
1010
|
for (const x of _data) {
|
1019
1011
|
const copy = { ...x };
|
1020
|
-
copy.offset += pages.size * pageSize;
|
1012
|
+
if (copy.offset != null) copy.offset += pages.size * pageSize;
|
1021
1013
|
data.push(copy);
|
1022
1014
|
}
|
1023
1015
|
|
@@ -1271,7 +1263,15 @@ const getNodeType = (scope, node) => {
|
|
1271
1263
|
}
|
1272
1264
|
|
1273
1265
|
if (node.type === 'AssignmentExpression') {
|
1274
|
-
|
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
|
+
});
|
1275
1275
|
}
|
1276
1276
|
|
1277
1277
|
if (node.type === 'ArrayExpression') {
|
@@ -1290,23 +1290,6 @@ const getNodeType = (scope, node) => {
|
|
1290
1290
|
if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) return TYPES.bytestring;
|
1291
1291
|
|
1292
1292
|
return TYPES.number;
|
1293
|
-
|
1294
|
-
// todo: string concat types
|
1295
|
-
// if (node.operator !== '+') return TYPES.number;
|
1296
|
-
// else return [
|
1297
|
-
// // if left is string
|
1298
|
-
// ...getNodeType(scope, node.left),
|
1299
|
-
// ...number(TYPES.string, Valtype.i32),
|
1300
|
-
// [ Opcodes.i32_eq ],
|
1301
|
-
|
1302
|
-
// // if right is string
|
1303
|
-
// ...getNodeType(scope, node.right),
|
1304
|
-
// ...number(TYPES.string, Valtype.i32),
|
1305
|
-
// [ Opcodes.i32_eq ],
|
1306
|
-
|
1307
|
-
// // if either are true
|
1308
|
-
// [ Opcodes.i32_or ],
|
1309
|
-
// ];
|
1310
1293
|
}
|
1311
1294
|
|
1312
1295
|
if (node.type === 'UnaryExpression') {
|
@@ -1326,7 +1309,6 @@ const getNodeType = (scope, node) => {
|
|
1326
1309
|
if (Prefs.fastLength) return TYPES.number;
|
1327
1310
|
}
|
1328
1311
|
|
1329
|
-
|
1330
1312
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1331
1313
|
if (objectKnownType != null) {
|
1332
1314
|
if (name === 'length') {
|
@@ -1337,7 +1319,6 @@ const getNodeType = (scope, node) => {
|
|
1337
1319
|
if (node.computed) {
|
1338
1320
|
if (objectKnownType === TYPES.string) return TYPES.string;
|
1339
1321
|
if (objectKnownType === TYPES.bytestring) return TYPES.bytestring;
|
1340
|
-
if (objectKnownType === TYPES.array) return TYPES.number;
|
1341
1322
|
}
|
1342
1323
|
}
|
1343
1324
|
|
@@ -1403,10 +1384,10 @@ const countLeftover = wasm => {
|
|
1403
1384
|
|
1404
1385
|
if (depth === 0)
|
1405
1386
|
if ([Opcodes.throw, Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1406
|
-
else if ([null, Opcodes.i32_eqz, Opcodes.i64_eqz, Opcodes.f64_ceil, Opcodes.f64_floor, Opcodes.f64_trunc, Opcodes.f64_nearest, Opcodes.f64_sqrt, Opcodes.local_tee, Opcodes.i32_wrap_i64, Opcodes.i64_extend_i32_s, Opcodes.i64_extend_i32_u, Opcodes.f32_demote_f64, Opcodes.f64_promote_f32, Opcodes.f64_convert_i32_s, Opcodes.f64_convert_i32_u, Opcodes.i32_clz, Opcodes.i32_ctz, Opcodes.i32_popcnt, Opcodes.f64_neg, Opcodes.end, Opcodes.i32_trunc_sat_f64_s[0], Opcodes.i32x4_extract_lane, Opcodes.i16x8_extract_lane, Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.i32_load8_u, Opcodes.i32_load8_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] <
|
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)) {}
|
1407
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++;
|
1408
1389
|
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1409
|
-
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;
|
1410
1391
|
else if (inst[0] === Opcodes.return) count = 0;
|
1411
1392
|
else if (inst[0] === Opcodes.call) {
|
1412
1393
|
let func = funcs.find(x => x.index === inst[1]);
|
@@ -1951,13 +1932,18 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1951
1932
|
continue;
|
1952
1933
|
}
|
1953
1934
|
|
1954
|
-
if (valtypeBinary !== Valtype.i32 &&
|
1935
|
+
if (valtypeBinary !== Valtype.i32 &&
|
1955
1936
|
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32)
|
1956
|
-
|
1957
|
-
)) {
|
1937
|
+
) {
|
1958
1938
|
out.push(Opcodes.i32_to);
|
1959
1939
|
}
|
1960
1940
|
|
1941
|
+
if (valtypeBinary === Valtype.i32 &&
|
1942
|
+
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.f64)
|
1943
|
+
) {
|
1944
|
+
out.push(Opcodes.f64_convert_i32_s);
|
1945
|
+
}
|
1946
|
+
|
1961
1947
|
if (typedParams) out = out.concat(getNodeType(scope, arg));
|
1962
1948
|
}
|
1963
1949
|
|
@@ -1979,6 +1965,10 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1979
1965
|
out.push(Opcodes.i32_from);
|
1980
1966
|
}
|
1981
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
|
+
|
1982
1972
|
return out;
|
1983
1973
|
};
|
1984
1974
|
|
@@ -2002,9 +1992,9 @@ const generateNew = (scope, decl, _global, _name) => {
|
|
2002
1992
|
if (
|
2003
1993
|
(builtinFuncs[name] && !builtinFuncs[name].constr) ||
|
2004
1994
|
(internalConstrs[name] && builtinFuncs[name].notConstr)
|
2005
|
-
) return internalThrow(scope, 'TypeError', `${name} is not a constructor
|
1995
|
+
) return internalThrow(scope, 'TypeError', `${name} is not a constructor`, true);
|
2006
1996
|
|
2007
|
-
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)})`);
|
2008
1998
|
|
2009
1999
|
return generateCall(scope, decl, _global, _name);
|
2010
2000
|
};
|
@@ -2452,9 +2442,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2452
2442
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2453
2443
|
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
2454
2444
|
|
2455
|
-
|
2456
|
-
|
2457
|
-
...setType(scope, name, TYPES.number)
|
2445
|
+
...setType(scope, name, getNodeType(scope, decl))
|
2458
2446
|
];
|
2459
2447
|
};
|
2460
2448
|
|
@@ -3117,8 +3105,6 @@ const allocPage = (scope, reason, type) => {
|
|
3117
3105
|
scope.pages ??= new Map();
|
3118
3106
|
scope.pages.set(reason, { ind, type });
|
3119
3107
|
|
3120
|
-
if (Prefs.allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
|
3121
|
-
|
3122
3108
|
return ind;
|
3123
3109
|
};
|
3124
3110
|
|
@@ -3156,6 +3142,46 @@ const compileBytes = (val, itemType) => {
|
|
3156
3142
|
}
|
3157
3143
|
};
|
3158
3144
|
|
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;
|
3155
|
+
|
3156
|
+
bytes.push(...compileBytes(elements[i], itemType));
|
3157
|
+
}
|
3158
|
+
|
3159
|
+
const obj = { bytes };
|
3160
|
+
if (offset != null) obj.offset = offset;
|
3161
|
+
|
3162
|
+
const idx = data.push(obj) - 1;
|
3163
|
+
|
3164
|
+
scope.data ??= [];
|
3165
|
+
scope.data.push(idx);
|
3166
|
+
|
3167
|
+
return { idx, size: bytes.length };
|
3168
|
+
};
|
3169
|
+
|
3170
|
+
const printStaticStr = str => {
|
3171
|
+
const out = [];
|
3172
|
+
|
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
|
+
);
|
3180
|
+
}
|
3181
|
+
|
3182
|
+
return out;
|
3183
|
+
};
|
3184
|
+
|
3159
3185
|
const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false, itemType = valtype, intOut = false, typed = false) => {
|
3160
3186
|
if (itemType !== 'i16' && itemType !== 'i8') {
|
3161
3187
|
pages.hasArray = true;
|
@@ -3175,17 +3201,50 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3175
3201
|
const valtype = itemTypeToValtype[itemType];
|
3176
3202
|
const length = elements.length;
|
3177
3203
|
|
3178
|
-
const allocated = allocator.alloc({ scope, pages, globals }, uniqueName, { itemType });
|
3204
|
+
const allocated = allocator.alloc({ scope, pages, globals, asmFunc, funcIndex }, uniqueName, { itemType });
|
3179
3205
|
|
3180
3206
|
let pointer = allocated;
|
3181
3207
|
if (allocator.constructor.name !== 'StaticAllocator') {
|
3182
|
-
const tmp = localTmp(scope, '#makearray_pointer' + uniqueName, Valtype.i32);
|
3208
|
+
// const tmp = localTmp(scope, '#makearray_pointer' + uniqueName, Valtype.i32);
|
3209
|
+
const tmp = localTmp(scope, '#makearray_pointer' + name, Valtype.i32);
|
3183
3210
|
out.push(
|
3184
3211
|
...allocated,
|
3185
3212
|
[ Opcodes.local_set, tmp ]
|
3186
3213
|
);
|
3187
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
|
+
);
|
3225
|
+
|
3188
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
|
+
);
|
3238
|
+
}
|
3239
|
+
|
3240
|
+
// return pointer in out
|
3241
|
+
out.push(
|
3242
|
+
...pointer,
|
3243
|
+
...(!intOut ? [ Opcodes.i32_from_u ] : [])
|
3244
|
+
);
|
3245
|
+
|
3246
|
+
return [ out, pointer ];
|
3247
|
+
}
|
3189
3248
|
} else {
|
3190
3249
|
const rawPtr = read_signedLEB128(pointer[0].slice(1));
|
3191
3250
|
|
@@ -3194,24 +3253,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3194
3253
|
if (firstAssign) scope.arrays.set(uniqueName, rawPtr);
|
3195
3254
|
|
3196
3255
|
if (Prefs.data && firstAssign && useRawElements) {
|
3197
|
-
|
3198
|
-
if (length !== 0) {
|
3199
|
-
let bytes = compileBytes(length, 'i32');
|
3200
|
-
|
3201
|
-
if (!initEmpty) for (let i = 0; i < length; i++) {
|
3202
|
-
if (elements[i] == null) continue;
|
3203
|
-
|
3204
|
-
bytes.push(...compileBytes(elements[i], itemType));
|
3205
|
-
}
|
3206
|
-
|
3207
|
-
const ind = data.push({
|
3208
|
-
offset: rawPtr,
|
3209
|
-
bytes
|
3210
|
-
}) - 1;
|
3211
|
-
|
3212
|
-
scope.data ??= [];
|
3213
|
-
scope.data.push(ind);
|
3214
|
-
}
|
3256
|
+
makeData(scope, elements, rawPtr, itemType, initEmpty);
|
3215
3257
|
|
3216
3258
|
// local value as pointer
|
3217
3259
|
return [ number(rawPtr, intOut ? Valtype.i32 : valtypeBinary), pointer ];
|
@@ -3479,7 +3521,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3479
3521
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3480
3522
|
// hack: this is naughty and will break things!
|
3481
3523
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3482
|
-
if (pages.hasAnyString) {
|
3524
|
+
if (pages.hasAnyString && knownType(scope, getNodeType(scope, decl.object)) !== TYPES.array) {
|
3483
3525
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3484
3526
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3485
3527
|
rawElements: new Array(0)
|
@@ -3694,9 +3736,9 @@ const internalConstrs = {
|
|
3694
3736
|
|
3695
3737
|
// new Array(n)
|
3696
3738
|
|
3697
|
-
const [ , pointer ] = makeArray(scope, {
|
3739
|
+
const [ out, pointer ] = makeArray(scope, {
|
3698
3740
|
rawElements: new Array(0)
|
3699
|
-
}, global, name, true);
|
3741
|
+
}, global, name, true, undefined, true);
|
3700
3742
|
|
3701
3743
|
const arg = decl.arguments[0] ?? DEFAULT_VALUE;
|
3702
3744
|
|
@@ -3705,7 +3747,7 @@ const internalConstrs = {
|
|
3705
3747
|
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeThrow', 'Invalid array length', true);
|
3706
3748
|
|
3707
3749
|
return [
|
3708
|
-
...
|
3750
|
+
...out,
|
3709
3751
|
...generate(scope, arg, global, name),
|
3710
3752
|
Opcodes.i32_to_u,
|
3711
3753
|
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
@@ -3895,7 +3937,7 @@ export default program => {
|
|
3895
3937
|
builtinFuncs = new BuiltinFuncs();
|
3896
3938
|
builtinVars = new BuiltinVars();
|
3897
3939
|
prototypeFuncs = new PrototypeFuncs();
|
3898
|
-
allocator =
|
3940
|
+
allocator = makeAllocator(Prefs.allocator ?? 'static');
|
3899
3941
|
|
3900
3942
|
program.id = { name: 'main' };
|
3901
3943
|
|