@asmlift/core 0.9.0 → 0.11.0

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.
Files changed (117) hide show
  1. package/README.md +25 -24
  2. package/package.json +1 -1
  3. package/src/aggregate.ts +149 -0
  4. package/src/backend/c.ts +2 -0
  5. package/src/backend/cfamily.ts +197 -61
  6. package/src/backend/cpp.ts +3 -1
  7. package/src/backend/lines.ts +10 -0
  8. package/src/backend/pascal.ts +47 -16
  9. package/src/cdecl/parse.ts +21 -0
  10. package/src/contracts.ts +246 -36
  11. package/src/declare.ts +69 -20
  12. package/src/frontend/arm-body.ts +155 -0
  13. package/src/frontend/asmdata.ts +9 -2
  14. package/src/frontend/call-plan.ts +1117 -61
  15. package/src/frontend/callee-body.ts +370 -0
  16. package/src/frontend/dead-reads.ts +628 -0
  17. package/src/frontend/device-pins.ts +33 -4
  18. package/src/frontend/emit.ts +4 -3
  19. package/src/frontend/fpu.ts +224 -17
  20. package/src/frontend/frame-objects.ts +1689 -206
  21. package/src/frontend/frontend.ts +84 -3
  22. package/src/frontend/high-half.ts +53 -4
  23. package/src/frontend/jump-table.ts +545 -0
  24. package/src/frontend/local-object.ts +158 -32
  25. package/src/frontend/mips.ts +2296 -217
  26. package/src/frontend/own-struct-return.ts +500 -0
  27. package/src/frontend/ppc.ts +2748 -245
  28. package/src/frontend/register-struct-call.ts +399 -0
  29. package/src/frontend/reloc-symbol.ts +22 -7
  30. package/src/frontend/ssa.ts +1721 -43
  31. package/src/frontend/stackargs.ts +199 -72
  32. package/src/frontend/thumb-entry.ts +340 -0
  33. package/src/frontend/thumb.ts +2400 -325
  34. package/src/ir/alias.ts +65 -2
  35. package/src/ir/bits.ts +1699 -4
  36. package/src/ir/core.ts +254 -9
  37. package/src/ir/discipline.ts +86 -21
  38. package/src/ir/entry.ts +157 -0
  39. package/src/{structure → ir}/loops.ts +6 -2
  40. package/src/ir/opcodes.ts +137 -9
  41. package/src/ir/parse.ts +1 -0
  42. package/src/ir/simplify.ts +61 -10
  43. package/src/ir/types.ts +86 -2
  44. package/src/ir/verify.ts +96 -11
  45. package/src/l3/argbase.ts +2 -0
  46. package/src/l3/ast.ts +582 -18
  47. package/src/l3/basecse.ts +68 -15
  48. package/src/l3/caseendgoto.ts +223 -0
  49. package/src/l3/coalesce.ts +42 -14
  50. package/src/l3/constinit.ts +410 -0
  51. package/src/l3/dce.ts +53 -9
  52. package/src/l3/initfirst.ts +42 -11
  53. package/src/l3/intcell.ts +2 -1
  54. package/src/l3/narrowdecl.ts +77 -36
  55. package/src/l3/pollguard.ts +8 -2
  56. package/src/l3/ptrcell.ts +33 -34
  57. package/src/l3/ptrfield.ts +123 -8
  58. package/src/l3/regspell.ts +11 -4
  59. package/src/l3/reindex.ts +295 -99
  60. package/src/l3/scopebase.ts +2 -0
  61. package/src/l3/storage.ts +98 -1
  62. package/src/l3/symbol-refs.ts +84 -6
  63. package/src/l3/tailmerge.ts +6 -2
  64. package/src/l3/typing.ts +108 -15
  65. package/src/l3/unreduce.ts +6 -5
  66. package/src/l3/volatileptr.ts +17 -54
  67. package/src/mangle.ts +30 -0
  68. package/src/pattern/engine.ts +361 -73
  69. package/src/pipeline.ts +1039 -38
  70. package/src/proto-context.ts +1039 -45
  71. package/src/proto.ts +555 -40
  72. package/src/raise/aggmembers.ts +290 -0
  73. package/src/raise/arrays.ts +5 -1
  74. package/src/raise/const.ts +25 -0
  75. package/src/raise/declared-volatile.ts +207 -31
  76. package/src/raise/divpow2.ts +192 -0
  77. package/src/raise/floathelpers.ts +254 -33
  78. package/src/raise/gvn.ts +3 -3
  79. package/src/raise/latch.ts +162 -6
  80. package/src/raise/memberarrays.ts +10 -4
  81. package/src/raise/offsetnames.ts +422 -36
  82. package/src/raise/pairparams.ts +33 -0
  83. package/src/raise/paramwidth.ts +196 -6
  84. package/src/raise/pre-recovery.ts +107 -21
  85. package/src/raise/pre-structure.ts +73 -0
  86. package/src/raise/recover.ts +12 -5
  87. package/src/raise/reroll.ts +674 -0
  88. package/src/raise/shortcircuit.ts +217 -34
  89. package/src/raise/softdiv.ts +1 -1
  90. package/src/raise/storesign.ts +153 -0
  91. package/src/raise/struct-arrays.ts +30 -11
  92. package/src/raise/structs.ts +396 -33
  93. package/src/raise/truncload.ts +4 -3
  94. package/src/raise/unpre.ts +594 -0
  95. package/src/raise/unthread.ts +400 -0
  96. package/src/rank-declare.ts +118 -12
  97. package/src/rank-variations.ts +186 -35
  98. package/src/rank.ts +536 -68
  99. package/src/runtime-helpers.ts +140 -22
  100. package/src/structure/analysis.ts +217 -8
  101. package/src/structure/arith-ops.ts +23 -0
  102. package/src/structure/cross-jumped-tail.ts +216 -0
  103. package/src/structure/globalaccess.ts +157 -10
  104. package/src/structure/hazards.ts +16 -64
  105. package/src/structure/local-statics.ts +145 -9
  106. package/src/structure/namecoalesce.ts +1 -1
  107. package/src/structure/pointer-spelling.ts +1106 -0
  108. package/src/structure/redundant-test.ts +1 -1
  109. package/src/structure/structure.ts +6192 -1213
  110. package/src/structure/switch-recover.ts +583 -120
  111. package/src/structure/unfolded-branch-constant.ts +90 -0
  112. package/src/symbols.ts +58 -15
  113. package/src/target.ts +1028 -54
  114. package/src/trace.ts +49 -17
  115. package/src/variation-definitions.ts +333 -20
  116. package/src/variation-gates.ts +4 -0
  117. package/src/variation-tokens.ts +68 -3
@@ -67,8 +67,13 @@ const TOKENS = [
67
67
  // lift: the assembly lifted or raised again
68
68
  { name: 'setup-args', variationKind: 'lift' },
69
69
  { name: 'connective', variationKind: 'lift' },
70
+ { name: 'narrow-param', variationKind: 'lift' },
70
71
  { name: 'shared-ret', variationKind: 'lift' },
72
+ { name: 'ret-copy', variationKind: 'lift' },
73
+ { name: 'ret-join', variationKind: 'lift' },
71
74
  { name: 'shared-tail', variationKind: 'lift' },
75
+ { name: 'kept-slot', variationKind: 'lift' },
76
+ { name: 'far-cast', variationKind: 'lift' },
72
77
  // structure: `structure()` re-run with other options
73
78
  { name: 'flip-branch', variationKind: 'structure' },
74
79
  { name: 'defsite', variationKind: 'structure' },
@@ -86,12 +91,16 @@ const TOKENS = [
86
91
  { name: 'derived-home', variationKind: 'structure' },
87
92
  { name: 'merge-home', variationKind: 'structure' },
88
93
  { name: 'escape-home', variationKind: 'structure' },
89
- { name: 'uns-cmp', variationKind: 'structure' },
94
+ { name: 'signed-cmp', variationKind: 'structure' },
90
95
  { name: 'fresh-merge', variationKind: 'structure' },
91
96
  { name: 'copy-defpos', variationKind: 'structure' },
92
97
  { name: 'site-sense', variationKind: 'structure' },
98
+ { name: 'tail-copies', variationKind: 'structure' },
99
+ { name: 'for-continue', variationKind: 'structure' },
100
+ { name: 'case-goto', variationKind: 'structure' },
93
101
  // respell: the structured tree rewritten
94
102
  { name: 'unmerge', variationKind: 'respell' },
103
+ { name: 'case-end-goto', variationKind: 'respell' },
95
104
  { name: 'argbase', variationKind: 'respell' },
96
105
  { name: 'zerosub', variationKind: 'respell' },
97
106
  { name: 'volatile', variationKind: 'respell', subject: LOCALS },
@@ -131,6 +140,7 @@ const TOKENS = [
131
140
  { name: 'pollguard', variationKind: 'respell' },
132
141
  { name: 'pollread', variationKind: 'respell' },
133
142
  { name: 'narrow-decl', variationKind: 'respell' },
143
+ { name: 'narrow-load', variationKind: 'respell' },
134
144
  { name: 'narrow-read', variationKind: 'respell' },
135
145
  {
136
146
  name: 'int-cell',
@@ -289,6 +299,40 @@ export function splitVariations(name: string): string[] {
289
299
  return variations;
290
300
  }
291
301
 
302
+ /** What is wrong with one candidate's name, or `undefined`: no variation at all, a variation the
303
+ * registry does not hold, a first variation that is not a signedness, or a variation after one of
304
+ * a later kind. The mint sites are typed, so none of these is a `tsc` error; enumeration data is
305
+ * the only place one shows, and `tallyFanVariations` asks this of every candidate it counts. */
306
+ export function variationsDefect(variations: readonly string[]): string | undefined {
307
+ try {
308
+ return orderDefect(variations, (part) => kindIndex(parseVariation(part).name));
309
+ } catch (e) {
310
+ return `${variations.join('/')}: ${e instanceof Error ? e.message : String(e)}`;
311
+ }
312
+ }
313
+
314
+ const kindIndex = (name: string): number => VARIATION_KINDS.indexOf(variationToken(name).variationKind);
315
+
316
+ /** `variationsDefect` past the registry lookup, which `kindOf` does (and throws from) so the tally
317
+ * can serve it from its own cache. */
318
+ function orderDefect(variations: readonly string[], kindOf: (part: string) => number): string | undefined {
319
+ if (variations.length === 0) {
320
+ return 'a candidate with no variations: it applies at least its signedness';
321
+ }
322
+ let previous = -1;
323
+ for (const [i, part] of variations.entries()) {
324
+ const kind = kindOf(part);
325
+ if (i === 0 && VARIATION_KINDS[kind] !== 'signedness') {
326
+ return `${variations.join('/')}: the first variation is '${part}', not a signedness`;
327
+ }
328
+ if (kind < previous) {
329
+ return `${variations.join('/')}: '${part}' (${VARIATION_KINDS[kind]}) after a ${VARIATION_KINDS[previous]} variation`;
330
+ }
331
+ previous = kind;
332
+ }
333
+ return undefined;
334
+ }
335
+
292
336
  /** How many of one fan's candidates carry one variation. `candidates` counts the whole fan —
293
337
  * scored, dropped, withheld and never compiled alike — and `dropped`, `withheld` and
294
338
  * `notCompiled` are the parts of that count the ranking did not score, each absent when 0.
@@ -315,7 +359,15 @@ interface NamedCandidate {
315
359
  *
316
360
  * A tally, not a factorisation: enumeration gates prune the fan, so the counts do not multiply to
317
361
  * its size. Keys run in kind order, then by name, so two tallies of one fan serialize to the same
318
- * bytes whatever order the fan was listed in. Throws on a variation the registry does not hold. */
362
+ * bytes whatever order the fan was listed in.
363
+ *
364
+ * Throws on any candidate whose name `variationsDefect` refuses — an unregistered variation, a
365
+ * first variation that is not a signedness, parts out of kind order. The bench tallies every fan
366
+ * it ranks to a verdict or refuses whole, every candidate of it, on both tiers, so this is where a
367
+ * malformed mint is caught: the artifact keeps only the winner's and the refused candidates' names,
368
+ * and a test that re-enumerated the synthetic tier to read the rest cost minutes and never saw the
369
+ * real one. A rank a scorer dies in leaves a `noncompile` row with no fan, so nothing is tallied
370
+ * there. */
319
371
  export function tallyFanVariations(fan: {
320
372
  candidates: readonly NamedCandidate[];
321
373
  dropped: readonly NamedCandidate[];
@@ -331,9 +383,23 @@ export function tallyFanVariations(fan: {
331
383
  }
332
384
  return name;
333
385
  };
386
+ const kindOfName = new Map<string, number>();
387
+ const kindOf = (part: string): number => {
388
+ const name = nameOf(part);
389
+ let kind = kindOfName.get(name);
390
+ if (kind === undefined) {
391
+ kind = kindIndex(name);
392
+ kindOfName.set(name, kind);
393
+ }
394
+ return kind;
395
+ };
334
396
  const counts = new Map<string, { candidates: number; dropped: number; withheld: number; notCompiled: number }>();
335
397
  const add = (list: readonly NamedCandidate[], refusal: 'dropped' | 'withheld' | 'notCompiled' | undefined): void => {
336
398
  for (const c of list) {
399
+ const defect = orderDefect(c.variations, kindOf);
400
+ if (defect !== undefined) {
401
+ throw new Error(`a fan candidate's name is malformed — ${defect} (packages/core/src/variation-tokens.ts)`);
402
+ }
337
403
  for (const name of new Set(c.variations.map(nameOf))) {
338
404
  let n = counts.get(name);
339
405
  if (n === undefined) {
@@ -351,7 +417,6 @@ export function tallyFanVariations(fan: {
351
417
  add(fan.dropped, 'dropped');
352
418
  add(fan.withheld, 'withheld');
353
419
  add(fan.notCompiled, 'notCompiled');
354
- const kindIndex = (name: string): number => VARIATION_KINDS.indexOf(variationToken(name).variationKind);
355
420
  const names = [...counts.keys()].sort((a, b) => kindIndex(a) - kindIndex(b) || (a < b ? -1 : a > b ? 1 : 0));
356
421
  return Object.fromEntries(
357
422
  names.map((name) => {