@asmlift/core 0.6.0 → 0.8.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 (88) hide show
  1. package/README.md +48 -24
  2. package/package.json +1 -1
  3. package/src/backend/cfamily.ts +39 -11
  4. package/src/backend/pascal.ts +2 -2
  5. package/src/codegen-flags.ts +640 -0
  6. package/src/contracts.ts +60 -11
  7. package/src/frontend/disasm.ts +141 -11
  8. package/src/frontend/high-half.ts +149 -0
  9. package/src/frontend/mips.ts +458 -209
  10. package/src/frontend/ppc.ts +332 -67
  11. package/src/frontend/reloc-symbol.ts +109 -0
  12. package/src/frontend/splat.ts +56 -18
  13. package/src/frontend/ssa.ts +127 -30
  14. package/src/frontend/stackargs.ts +420 -0
  15. package/src/frontend/thumb.ts +209 -232
  16. package/src/ir/alias.ts +24 -0
  17. package/src/ir/core.ts +70 -3
  18. package/src/ir/opcodes.ts +52 -7
  19. package/src/ir/parse.ts +7 -1
  20. package/src/ir/simplify.ts +1 -1
  21. package/src/l3/address.ts +2 -2
  22. package/src/l3/advance.ts +373 -0
  23. package/src/l3/argbase.ts +6 -6
  24. package/src/l3/argcopy.ts +269 -0
  25. package/src/l3/ast.ts +110 -22
  26. package/src/l3/basecse.ts +50 -30
  27. package/src/l3/coalesce.ts +118 -61
  28. package/src/l3/gates.ts +75 -1
  29. package/src/l3/hoist.ts +1 -1
  30. package/src/l3/homesplit.ts +13 -13
  31. package/src/l3/initfirst.ts +3 -3
  32. package/src/l3/inlinebase.ts +16 -16
  33. package/src/l3/mentions.ts +68 -5
  34. package/src/l3/mulfirst.ts +3 -3
  35. package/src/l3/nearbase.ts +4 -4
  36. package/src/l3/offmember.ts +5 -5
  37. package/src/l3/parkfirst.ts +6 -6
  38. package/src/l3/pollguard.ts +3 -3
  39. package/src/l3/ptrfield.ts +4 -4
  40. package/src/l3/regspell.ts +8 -8
  41. package/src/l3/reindex.ts +22 -17
  42. package/src/l3/scopebase.ts +32 -29
  43. package/src/l3/sinkinit.ts +7 -7
  44. package/src/l3/slotorder.ts +3 -3
  45. package/src/l3/storage.ts +1 -1
  46. package/src/l3/tailmerge.ts +2 -2
  47. package/src/l3/tailret.ts +70 -0
  48. package/src/l3/typing.ts +3 -3
  49. package/src/l3/unmerge.ts +483 -59
  50. package/src/l3/unreduce.ts +15 -14
  51. package/src/l3/volatileptr.ts +11 -11
  52. package/src/l3/volatileval.ts +11 -11
  53. package/src/l3/volstore.ts +16 -16
  54. package/src/l3/zerosub.ts +6 -6
  55. package/src/mangle.ts +49 -0
  56. package/src/pattern/engine.ts +132 -17
  57. package/src/pipeline.ts +39 -16
  58. package/src/proto.ts +2 -2
  59. package/src/raise/const.ts +203 -3
  60. package/src/raise/divpow2.ts +2 -2
  61. package/src/raise/extscale.ts +345 -0
  62. package/src/raise/globalshape.ts +32 -12
  63. package/src/raise/gvn.ts +2 -2
  64. package/src/raise/magicdiv.ts +2 -2
  65. package/src/raise/memberarrays.ts +4 -4
  66. package/src/raise/narrowlocal.ts +18 -2
  67. package/src/raise/paramwidth.ts +133 -3
  68. package/src/raise/pre-recovery.ts +100 -25
  69. package/src/raise/retsink.ts +389 -19
  70. package/src/raise/shortcircuit.ts +595 -34
  71. package/src/raise/structs.ts +4 -4
  72. package/src/raise/tailsink.ts +141 -0
  73. package/src/rank-declare.ts +21 -13
  74. package/src/{rank-axes.ts → rank-variations.ts} +319 -189
  75. package/src/rank.ts +1176 -805
  76. package/src/structure/analysis.ts +87 -90
  77. package/src/structure/bitfields.ts +130 -30
  78. package/src/structure/globalaccess.ts +30 -4
  79. package/src/structure/namecoalesce.ts +32 -13
  80. package/src/structure/retspell.ts +95 -0
  81. package/src/structure/structure.ts +1425 -201
  82. package/src/structure/switch-recover.ts +101 -8
  83. package/src/symbols.ts +127 -6
  84. package/src/target.ts +374 -44
  85. package/src/trace.ts +28 -19
  86. package/src/variation-definitions.ts +1590 -0
  87. package/src/variation-gates.ts +92 -0
  88. package/src/variation-tokens.ts +356 -0
package/src/trace.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  // (objdiff score, per-pattern score deltas via the `probeScore` hook, ranked candidates) when a
6
6
  // target object is available; the web playground renders the TraceReport as-is.
7
7
  import { cBackend } from './backend/c';
8
+ import type { CodegenProfile } from './codegen-flags';
8
9
  import type { AsmData } from './frontend/asmdata';
9
10
  import { frontendFor } from './frontend/registry';
10
11
  import type { Fn } from './ir/core';
@@ -16,7 +17,7 @@ import { type OnGap, raiseRecovered, structureChecked, stubResult } from './pipe
16
17
  import { type Prototypes, prototypesFromSymbols } from './proto';
17
18
  import { assumedShapes, inferGlobalArrays, orderLicensedGlobals } from './raise/globalshape';
18
19
  import { type SymbolInfo, type SymbolMap, symbolsByName } from './symbols';
19
- import { type TargetDescription, structureOptionsFor } from './target';
20
+ import { type ResolvedTarget, type TargetDescription, type ToolchainId, structureOptionsFor } from './target';
20
21
 
21
22
  /** EVERY stage dump carries the write-order record (ir/print.ts `PrintOptions`) — not just
22
23
  * `stage:lift`, even though only the frontend measures it. Two reasons: the raising folds MUTATE
@@ -50,6 +51,11 @@ export interface TraceReport {
50
51
  target: {
51
52
  isa: string;
52
53
  compiler: string;
54
+ toolchain: ToolchainId;
55
+ /** the flags the function was compiled with, in the build's order */
56
+ cflags: readonly string[];
57
+ /** what those flags make the compiler do */
58
+ profile: Pick<CodegenProfile, 'slots'>;
53
59
  capabilities: TargetDescription['capabilities'];
54
60
  compilerBehaviors: TargetDescription['compilerBehaviors'];
55
61
  };
@@ -118,19 +124,31 @@ const PRE_RECOVERY_TRACE: Record<string, { stage: string; title: (result: number
118
124
  'struct-arrays': { stage: 'stage:struct-arrays', title: () => 'Struct-array recovery (element stride evidence)' },
119
125
  };
120
126
 
127
+ function reportTarget({ toolchain, cflags, target, profile }: ResolvedTarget): TraceReport['target'] {
128
+ return {
129
+ isa: target.id,
130
+ compiler: target.compiler,
131
+ toolchain,
132
+ cflags,
133
+ profile: { slots: profile.slots },
134
+ capabilities: target.capabilities,
135
+ compilerBehaviors: target.compilerBehaviors,
136
+ };
137
+ }
138
+
121
139
  /** Run the tower while recording a TraceReport. Strict mode throws on any gap (like decompile);
122
140
  * annotate mode never throws — a non-localizable failure degrades to the same stub. */
123
141
  export function decompileTraced(
124
142
  name: string,
125
143
  asm: string,
126
- target: TargetDescription,
144
+ resolved: ResolvedTarget,
127
145
  opts: TraceOptions = {},
128
146
  ): { source: string; report: TraceReport } {
129
147
  if ((opts.onGap ?? 'strict') === 'strict') {
130
- return traceTower(name, asm, target, opts);
148
+ return traceTower(name, asm, resolved, opts);
131
149
  }
132
150
  try {
133
- return traceTower(name, asm, target, opts);
151
+ return traceTower(name, asm, resolved, opts);
134
152
  } catch (e) {
135
153
  // Annotate-mode parity with decompile(): a NON-localizable failure degrades to the SAME
136
154
  // stub (reason + original asm as comments) instead of a throw.
@@ -141,12 +159,7 @@ export function decompileTraced(
141
159
  version: 1,
142
160
  type: 'decompile',
143
161
  symbol: name,
144
- target: {
145
- isa: target.id,
146
- compiler: target.compiler,
147
- capabilities: target.capabilities,
148
- compilerBehaviors: target.compilerBehaviors,
149
- },
162
+ target: reportTarget(resolved),
150
163
  asm,
151
164
  trace: [],
152
165
  patternEvents: [],
@@ -161,9 +174,10 @@ export function decompileTraced(
161
174
  function traceTower(
162
175
  name: string,
163
176
  asm: string,
164
- target: TargetDescription,
177
+ resolved: ResolvedTarget,
165
178
  opts: TraceOptions,
166
179
  ): { source: string; report: TraceReport } {
180
+ const { target } = resolved;
167
181
  const backend = opts.backend ?? cBackend;
168
182
  // Merged exactly as pipeline.ts does: the project's own DWARF signatures fill in what the caller
169
183
  // did not state. A trace that lifted from a different table would explain a run that never
@@ -207,7 +221,7 @@ function traceTower(
207
221
  let scoreBefore = opts.probeScore?.(fn, inferredSymbols);
208
222
  for (const p of active) {
209
223
  const beforeIr = irDump(fn);
210
- const hits = applyPattern(fn, p);
224
+ const hits = applyPattern(fn, p, target);
211
225
  dce(fn);
212
226
  verify(fn);
213
227
  if (hits === 0) {
@@ -280,7 +294,7 @@ function traceTower(
280
294
  );
281
295
 
282
296
  // (4) structure → neutral AST; boundary contract: no unresolved value leaked (strict) or
283
- // spelled as a loud ASMLIFT_ERROR marker (annotate) — same onGap lever as decompile()
297
+ // spelled as a loud ASMLIFT_ERROR marker (annotate) — same onGap option as decompile()
284
298
  const mapSymbols = opts.symbols ? symbolsByName(opts.symbols) : undefined;
285
299
  const sfn = structureChecked(fn, {
286
300
  ...structureOptionsFor(target, returnsVoid),
@@ -307,12 +321,7 @@ function traceTower(
307
321
  version: 1,
308
322
  type: 'decompile',
309
323
  symbol: name,
310
- target: {
311
- isa: target.id,
312
- compiler: target.compiler,
313
- capabilities: target.capabilities,
314
- compilerBehaviors: target.compilerBehaviors,
315
- },
324
+ target: reportTarget(resolved),
316
325
  asm,
317
326
  trace,
318
327
  patternEvents,