porffor 0.2.0-3272f21 → 0.2.0-3aaa9b4

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.
@@ -7,23 +7,40 @@ type PorfforGlobal = {
7
7
  wasm: {
8
8
  (...args: any[]): any;
9
9
  i32: {
10
- or(a: i32, b: i32): i32;
11
-
12
10
  load(pointer: i32, align: i32, offset: i32): i32;
13
11
  store(pointer: i32, value: i32, align: i32, offset: i32): i32;
14
12
  load8_u(pointer: i32, align: i32, offset: i32): i32;
15
13
  store8(pointer: i32, value: i32, align: i32, offset: i32): i32;
16
14
  load16_u(pointer: i32, align: i32, offset: i32): i32;
17
15
  store16(pointer: i32, value: i32, align: i32, offset: i32): i32;
16
+ const(value: i32): i32;
17
+ }
18
+
19
+ f64: {
20
+ load(pointer: i32, align: i32, offset: i32): i32;
21
+ store(pointer: i32, value: f64, align: i32, offset: i32): f64;
18
22
  }
19
23
  }
20
24
 
21
- // randomInt(): i32;
22
25
  randomByte(): i32;
23
26
 
24
27
  type(x: any): bytestring;
25
28
  rawType(x: any): i32;
26
- TYPES: Record<string, i32>;
29
+ TYPES: {
30
+ number: i32;
31
+ boolean: i32;
32
+ string: i32;
33
+ undefined: i32;
34
+ object: i32;
35
+ function: i32;
36
+ symbol: i32;
37
+ bigint: i32;
38
+
39
+ _array: i32;
40
+ _regexp: i32;
41
+ _bytestring: i32;
42
+ _date: i32;
43
+ }
27
44
 
28
45
  fastOr(...args: any): boolean;
29
46
  fastAnd(...args: any): boolean;
@@ -1,4 +1,4 @@
1
- // @porf -funsafe-no-unlikely-proto-checks -valtype=i32
1
+ // @porf --funsafe-no-unlikely-proto-checks --valtype=i32
2
2
 
3
3
  export const __String_fromCharCode = (code: i32) => {
4
4
  // todo: support >1 arg
@@ -1,4 +1,4 @@
1
- // // @porf -funsafe-no-unlikely-proto-checks -valtype=i32
1
+ // // @porf --funsafe-no-unlikely-proto-checks --valtype=i32
2
2
 
3
3
  export const __Boolean_prototype_toString = (_this: boolean) => {
4
4
  let out: bytestring = '';
@@ -201,7 +201,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
201
201
  }
202
202
 
203
203
  let inst = Opcodes[asm[0].replace('.', '_')];
204
- if (!inst) throw new Error(`inline asm: inst ${asm[0]} not found`);
204
+ if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
205
205
 
206
206
  if (!Array.isArray(inst)) inst = [ inst ];
207
207
  const immediates = asm.slice(1).map(x => {
@@ -460,7 +460,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
460
460
  const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
461
461
  const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
462
462
 
463
- if (assign) {
463
+ if (assign && Prefs.aotPointerOpt) {
464
464
  const pointer = scope.arrays?.get(name ?? '$undeclared');
465
465
 
466
466
  return [
@@ -1646,18 +1646,25 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1646
1646
  // megahack for /regex/.func()
1647
1647
  const funcName = decl.callee.property.name;
1648
1648
  if (decl.callee.object.regex && Object.hasOwn(Rhemyn, funcName)) {
1649
- const func = Rhemyn[funcName](decl.callee.object.regex.pattern, currentFuncIndex++);
1649
+ const regex = decl.callee.object.regex.pattern;
1650
+ const rhemynName = `regex_${funcName}_${regex}`;
1650
1651
 
1651
- funcIndex[func.name] = func.index;
1652
- funcs.push(func);
1652
+ if (!funcIndex[rhemynName]) {
1653
+ const func = Rhemyn[funcName](regex, currentFuncIndex++, rhemynName);
1653
1654
 
1655
+ funcIndex[func.name] = func.index;
1656
+ funcs.push(func);
1657
+ }
1658
+
1659
+ const idx = funcIndex[rhemynName];
1654
1660
  return [
1655
1661
  // make string arg
1656
1662
  ...generate(scope, decl.arguments[0]),
1663
+ Opcodes.i32_to_u,
1664
+ ...getNodeType(scope, decl.arguments[0]),
1657
1665
 
1658
1666
  // call regex func
1659
- Opcodes.i32_to_u,
1660
- [ Opcodes.call, func.index ],
1667
+ [ Opcodes.call, idx ],
1661
1668
  Opcodes.i32_from_u,
1662
1669
 
1663
1670
  ...number(TYPES.boolean, Valtype.i32),
@@ -1820,20 +1827,20 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1820
1827
  idx = funcIndex[name];
1821
1828
 
1822
1829
  // infer arguments types from builtins params
1823
- const func = funcs.find(x => x.name === name);
1824
- for (let i = 0; i < decl.arguments.length; i++) {
1825
- const arg = decl.arguments[i];
1826
- if (!arg.name) continue;
1827
-
1828
- const local = scope.locals[arg.name];
1829
- if (!local) continue;
1830
-
1831
- local.type = func.params[i];
1832
- if (local.type === Valtype.v128) {
1833
- // specify vec subtype inferred from last vec type in function name
1834
- local.vecType = name.split('_').reverse().find(x => x.includes('x'));
1835
- }
1836
- }
1830
+ // const func = funcs.find(x => x.name === name);
1831
+ // for (let i = 0; i < decl.arguments.length; i++) {
1832
+ // const arg = decl.arguments[i];
1833
+ // if (!arg.name) continue;
1834
+
1835
+ // const local = scope.locals[arg.name];
1836
+ // if (!local) continue;
1837
+
1838
+ // local.type = func.params[i];
1839
+ // if (local.type === Valtype.v128) {
1840
+ // // specify vec subtype inferred from last vec type in function name
1841
+ // local.vecType = name.split('_').reverse().find(x => x.includes('x'));
1842
+ // }
1843
+ // }
1837
1844
  }
1838
1845
 
1839
1846
  if (idx === undefined && internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
@@ -1865,9 +1872,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1865
1872
 
1866
1873
  // value
1867
1874
  i32_const: { imms: 1, args: [], returns: 1 },
1868
-
1869
- // a, b
1870
- i32_or: { imms: 0, args: [ true, true ], returns: 1 },
1871
1875
  };
1872
1876
 
1873
1877
  const opName = name.slice('__Porffor_wasm_'.length);
@@ -2205,6 +2209,7 @@ const generateVar = (scope, decl) => {
2205
2209
 
2206
2210
  // global variable if in top scope (main) and var ..., or if wanted
2207
2211
  const global = topLevel || decl._bare; // decl.kind === 'var';
2212
+ const target = global ? globals : scope.locals;
2208
2213
 
2209
2214
  for (const x of decl.declarations) {
2210
2215
  const name = mapName(x.id.name);
@@ -2226,6 +2231,10 @@ const generateVar = (scope, decl) => {
2226
2231
  continue; // always ignore
2227
2232
  }
2228
2233
 
2234
+ // // generate init before allocating var
2235
+ // let generated;
2236
+ // if (x.init) generated = generate(scope, x.init, global, name);
2237
+
2229
2238
  const typed = typedInput && x.id.typeAnnotation;
2230
2239
  let idx = allocVar(scope, name, global, !(typed && extractTypeAnnotation(x.id).type != null));
2231
2240
 
@@ -2234,9 +2243,17 @@ const generateVar = (scope, decl) => {
2234
2243
  }
2235
2244
 
2236
2245
  if (x.init) {
2237
- out = out.concat(generate(scope, x.init, global, name));
2238
-
2239
- out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2246
+ const generated = generate(scope, x.init, global, name);
2247
+ if (scope.arrays?.get(name) != null) {
2248
+ // hack to set local as pointer before
2249
+ out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2250
+ if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
2251
+ generated.pop();
2252
+ out = out.concat(generated);
2253
+ } else {
2254
+ out = out.concat(generated);
2255
+ out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2256
+ }
2240
2257
  out.push(...setType(scope, name, getNodeType(scope, x.init)));
2241
2258
  }
2242
2259
 
@@ -2263,6 +2280,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2263
2280
  return [];
2264
2281
  }
2265
2282
 
2283
+ const op = decl.operator.slice(0, -1) || '=';
2284
+
2266
2285
  // hack: .length setter
2267
2286
  if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
2268
2287
  const name = decl.left.object.name;
@@ -2271,14 +2290,20 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2271
2290
  const aotPointer = Prefs.aotPointerOpt && pointer != null;
2272
2291
 
2273
2292
  const newValueTmp = localTmp(scope, '__length_setter_tmp');
2293
+ const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
2274
2294
 
2275
2295
  return [
2276
2296
  ...(aotPointer ? number(0, Valtype.i32) : [
2277
2297
  ...generate(scope, decl.left.object),
2278
2298
  Opcodes.i32_to_u
2279
2299
  ]),
2300
+ ...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2280
2301
 
2281
- ...generate(scope, decl.right),
2302
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2303
+ [ Opcodes.local_get, pointerTmp ],
2304
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
2305
+ Opcodes.i32_from_u
2306
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right))),
2282
2307
  [ Opcodes.local_tee, newValueTmp ],
2283
2308
 
2284
2309
  Opcodes.i32_to_u,
@@ -2288,8 +2313,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2288
2313
  ];
2289
2314
  }
2290
2315
 
2291
- const op = decl.operator.slice(0, -1) || '=';
2292
-
2293
2316
  // arr[i]
2294
2317
  if (decl.left.type === 'MemberExpression' && decl.left.computed) {
2295
2318
  const name = decl.left.object.name;
@@ -3093,12 +3116,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3093
3116
  // todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
3094
3117
  const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
3095
3118
 
3096
- if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${scope.name} | ${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
3119
+ if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType) * pageSize);
3097
3120
  else scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
3098
3121
  }
3099
3122
 
3100
3123
  const pointer = scope.arrays.get(name);
3101
3124
 
3125
+ const local = global ? globals[name] : scope.locals[name];
3126
+
3102
3127
  const useRawElements = !!decl.rawElements;
3103
3128
  const elements = useRawElements ? decl.rawElements : decl.elements;
3104
3129
 
@@ -3131,11 +3156,22 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3131
3156
  return [ out, pointer ];
3132
3157
  }
3133
3158
 
3159
+ const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
3160
+ if (pointerTmp != null) {
3161
+ out.push(
3162
+ [ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
3163
+ Opcodes.i32_to_u,
3164
+ [ Opcodes.local_set, pointerTmp ]
3165
+ );
3166
+ }
3167
+
3168
+ const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
3169
+
3134
3170
  // store length as 0th array
3135
3171
  out.push(
3136
- ...number(0, Valtype.i32),
3172
+ ...pointerWasm,
3137
3173
  ...number(length, Valtype.i32),
3138
- [ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(pointer) ]
3174
+ [ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
3139
3175
  );
3140
3176
 
3141
3177
  const storeOp = StoreOps[itemType];
@@ -3144,14 +3180,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3144
3180
  if (elements[i] == null) continue;
3145
3181
 
3146
3182
  out.push(
3147
- ...number(0, Valtype.i32),
3183
+ ...pointerWasm,
3148
3184
  ...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
3149
- [ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
3185
+ [ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
3150
3186
  );
3151
3187
  }
3152
3188
 
3153
3189
  // local value as pointer
3154
- out.push(...number(pointer));
3190
+ out.push(...pointerWasm, Opcodes.i32_from_u);
3155
3191
 
3156
3192
  return [ out, pointer ];
3157
3193
  };
@@ -3649,7 +3685,7 @@ export default program => {
3649
3685
 
3650
3686
  globalThis.valtype = 'f64';
3651
3687
 
3652
- const valtypeOpt = process.argv.find(x => x.startsWith('-valtype='));
3688
+ const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
3653
3689
  if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
3654
3690
 
3655
3691
  globalThis.valtypeBinary = Valtype[valtype];
@@ -3657,7 +3693,7 @@ export default program => {
3657
3693
  const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
3658
3694
 
3659
3695
  globalThis.pageSize = PageSize;
3660
- const pageSizeOpt = process.argv.find(x => x.startsWith('-page-size='));
3696
+ const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
3661
3697
  if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
3662
3698
 
3663
3699
  // set generic opcodes for current valtype
@@ -110,7 +110,6 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
110
110
 
111
111
  out += '\n';
112
112
  lastInst = inst;
113
- i++;
114
113
  }
115
114
 
116
115
  return highlightAsm(out);