@fraczak/k 6.3.3 → 6.5.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 (157) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/DOCS/CODECS.md +258 -0
  3. package/DOCS/DICTIONARY.md +1172 -0
  4. package/DOCS/KIR_SPECIALIZATION_DESIGN.md +51 -46
  5. package/DOCS/KIR_V1.md +221 -0
  6. package/DOCS/KVM_EXECUTION_MODEL.md +56 -19
  7. package/DOCS/OBJECT_FILE_AND_PATTERN.md +2 -1
  8. package/DOCS/PROFILING_AND_TRACING.md +196 -0
  9. package/DOCS/REPL.md +61 -4
  10. package/DOCS/WEB_REPL_REQUIREMENTS.md +135 -0
  11. package/DOCS/dependency-graph.md +144 -0
  12. package/Examples/arithmetics.k +108 -82
  13. package/Examples/bnat.k +1 -1
  14. package/Examples/buda.k +44 -0
  15. package/Examples/ieee.k +300 -8671
  16. package/Examples/poly.k +67 -0
  17. package/README.md +68 -19
  18. package/Value.mjs +8 -2
  19. package/augmentation.mjs +9 -7
  20. package/backend-api.mjs +11 -2
  21. package/backends/arm64/README.md +104 -0
  22. package/backends/arm64/bin/k-arm64-compile.mjs +101 -0
  23. package/backends/arm64/bin/k-arm64-run.mjs +58 -0
  24. package/backends/arm64/bin/k-arm64.mjs +88 -0
  25. package/backends/arm64/scripts/run-tests.mjs +41 -0
  26. package/backends/arm64/src/arm64.mjs +229 -0
  27. package/backends/arm64/src/cli.mjs +155 -0
  28. package/backends/arm64/src/kvm2arm64.mjs +906 -0
  29. package/backends/arm64/src/runtime.c +728 -0
  30. package/backends/arm64/tests/integration.sh +112 -0
  31. package/backends/arm64/tests/test-arm64.mjs +240 -0
  32. package/backends/llvm/README.md +135 -0
  33. package/backends/llvm/bin/k-llvm-build.mjs +71 -0
  34. package/backends/llvm/bin/k-llvm-compile.mjs +68 -0
  35. package/backends/llvm/bin/k-llvm-jit.mjs +160 -0
  36. package/backends/llvm/bin/k-llvm-run.mjs +90 -0
  37. package/backends/llvm/runtime/krt.c +1508 -0
  38. package/backends/llvm/runtime/krt.h +109 -0
  39. package/backends/llvm/scripts/conformance.mjs +76 -0
  40. package/backends/llvm/scripts/run-tests.mjs +28 -0
  41. package/backends/llvm/src/executable.mjs +562 -0
  42. package/backends/llvm/src/kvm2llvm.mjs +998 -0
  43. package/backends/llvm/src/llvm.mjs +1092 -0
  44. package/backends/llvm/tests/composition-driver.c +22 -0
  45. package/backends/llvm/tests/identity-driver.c +27 -0
  46. package/backends/llvm/tests/integration.sh +153 -0
  47. package/backends/llvm/tests/perf-support.mjs +735 -0
  48. package/backends/llvm/tests/product-driver.c +23 -0
  49. package/backends/llvm/tests/projection-driver.c +19 -0
  50. package/backends/llvm/tests/relation-driver.c +29 -0
  51. package/backends/llvm/tests/test-llvm.mjs +240 -0
  52. package/backends/llvm/tests/union-driver.c +31 -0
  53. package/backends/llvm/tests/variant-driver.c +19 -0
  54. package/backends/llvm/tests/variant-projection-driver.c +21 -0
  55. package/backends/wasm/DOCS/USE-WEB-ASSEMBLY.md +233 -0
  56. package/backends/wasm/README.md +97 -0
  57. package/backends/wasm/TECHNICAL-DEBT.md +58 -0
  58. package/backends/wasm/bin/k-wasm-compile.mjs +50 -0
  59. package/backends/wasm/bin/k-wasm-run.mjs +140 -0
  60. package/backends/wasm/bin/k-wasm.mjs +49 -0
  61. package/backends/wasm/demo_ieee.mjs +319 -0
  62. package/backends/wasm/runtime.wat +475 -0
  63. package/backends/wasm/scripts/run-tests.mjs +41 -0
  64. package/backends/wasm/src/cli.mjs +133 -0
  65. package/backends/wasm/src/kvm2wasm.mjs +697 -0
  66. package/backends/wasm/src/wasm.mjs +1054 -0
  67. package/backends/wasm/tests/integration.sh +182 -0
  68. package/backends/wasm/tests/perf-support.mjs +336 -0
  69. package/backends/wasm/tests/test-wasm.mjs +625 -0
  70. package/browser/repl-browser.mjs +1584 -0
  71. package/browser/shims/assert.mjs +19 -0
  72. package/browser/shims/buffer.mjs +224 -0
  73. package/browser/shims/crypto.mjs +103 -0
  74. package/browser/shims/fs.mjs +159 -0
  75. package/browser/shims/os.mjs +17 -0
  76. package/browser/shims/path.mjs +54 -0
  77. package/browser/shims/process.mjs +44 -0
  78. package/browser/shims/readline.mjs +11 -0
  79. package/browser/shims/url.mjs +12 -0
  80. package/browser/vfs-data.mjs +19 -0
  81. package/codecs/README.md +3 -0
  82. package/codecs/runtime/show-value.mjs +12 -3
  83. package/conformance/helper-reuse/case.json +8 -0
  84. package/conformance/helper-reuse/expected.kv +1 -0
  85. package/conformance/helper-reuse/input.kv +1 -0
  86. package/conformance/helper-reuse/program.k +2 -0
  87. package/conformance/identity/case.json +8 -0
  88. package/conformance/identity/expected.kv +1 -0
  89. package/conformance/identity/input.kv +1 -0
  90. package/conformance/identity/program.k +1 -0
  91. package/conformance/product-projection/case.json +8 -0
  92. package/conformance/product-projection/expected.kv +1 -0
  93. package/conformance/product-projection/input.kv +1 -0
  94. package/conformance/product-projection/program.k +1 -0
  95. package/conformance/run.mjs +149 -0
  96. package/conformance/variant-construction/case.json +8 -0
  97. package/conformance/variant-construction/expected.kv +1 -0
  98. package/conformance/variant-construction/input.kv +1 -0
  99. package/conformance/variant-construction/program.k +1 -0
  100. package/harness/adapters/arm64.mjs +105 -0
  101. package/harness/adapters/kvm.mjs +144 -0
  102. package/harness/adapters/llvm.mjs +118 -0
  103. package/harness/adapters/native.mjs +77 -0
  104. package/harness/adapters/wasm.mjs +169 -0
  105. package/harness/backend.mjs +95 -0
  106. package/harness/cli.mjs +130 -0
  107. package/harness/format.mjs +95 -0
  108. package/harness/index.mjs +25 -0
  109. package/harness/persistent.mjs +121 -0
  110. package/harness/registry.mjs +44 -0
  111. package/harness/suite.mjs +257 -0
  112. package/harness/suites/poly.mjs +156 -0
  113. package/harness/trace.mjs +50 -0
  114. package/harness/util.mjs +92 -0
  115. package/intrinsics.mjs +41 -0
  116. package/kir.mjs +399 -0
  117. package/kvm.mjs +585 -81
  118. package/objects/README.md +37 -3
  119. package/objects/compile.mjs +15 -22
  120. package/objects/inspect.mjs +96 -0
  121. package/objects/validate.mjs +415 -0
  122. package/package.json +51 -19
  123. package/repl-codecs.mjs +105 -6
  124. package/repl.mjs +335 -49
  125. package/run.mjs +2 -7
  126. package/scripts/benchmark.mjs +406 -22
  127. package/scripts/build-repl-html.mjs +1784 -0
  128. package/scripts/perf-ieee.mjs +586 -0
  129. package/scripts/perf-int.mjs +531 -0
  130. package/scripts/perf-poly.mjs +945 -0
  131. package/scripts/render-benchmark.mjs +12 -8
  132. package/scripts/run-tests.mjs +6 -0
  133. package/tests/integration.sh +19 -2
  134. package/tests/test-arithmetics.mjs +54 -0
  135. package/tests/test-ieee-arithmetic.mjs +4 -0
  136. package/tests/test-kir.mjs +85 -0
  137. package/tests/test-kvm-polymorphic.mjs +278 -0
  138. package/tests/test-kvm.mjs +25 -6
  139. package/tests/test-poly.mjs +129 -0
  140. package/tests/test-repl-html.mjs +303 -0
  141. package/tests/test-repl.mjs +144 -1
  142. package/tests/test-validate-object.mjs +40 -0
  143. package/a.klib +0 -1
  144. package/a.kvm +0 -142676
  145. package/a.wasm +0 -0
  146. package/benchmark-results.html +0 -532
  147. package/benchmark-results.json +0 -480
  148. package/k-vscode/.vscode/launch.json +0 -14
  149. package/k-vscode/README.md +0 -75
  150. package/k-vscode/extension.js +0 -273
  151. package/k-vscode/language-configuration.json +0 -42
  152. package/k-vscode/package.json +0 -79
  153. package/k-vscode/snippets/k.json +0 -92
  154. package/k-vscode/syntaxes/k.tmLanguage.json +0 -599
  155. package/k-vscode/test/background-ranges.test.js +0 -50
  156. package/k-vscode/themes/k-contrast-color-theme.json +0 -104
  157. package/scripts/git-hooks/pre-commit +0 -10
@@ -0,0 +1,531 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import wabtFactory from "wabt";
6
+
7
+ import {
8
+ codes,
9
+ createState,
10
+ decodeWire,
11
+ evaluateInput,
12
+ exportPatternGraph,
13
+ patternToPropertyList,
14
+ propertyListToPattern,
15
+ run,
16
+ run_converged,
17
+ valueForCode
18
+ } from "@fraczak/k/backend-api.mjs";
19
+ import { parse as parseIntValue } from "@fraczak/k/codecs/int.mjs";
20
+
21
+ import {
22
+ csvEnv,
23
+ formatTiming,
24
+ createLLVMRunner,
25
+ createARM64Runner,
26
+ arm64LaneName,
27
+ llvmLaneName,
28
+ makeCacheDir,
29
+ parseNonNegativeIntEnv,
30
+ parsePositiveIntEnv,
31
+ prepareRelation,
32
+ printCompileFailures,
33
+ runExecutable,
34
+ runKVMCase,
35
+ runKVMIterations,
36
+ runNativeAwareIterations,
37
+ runNativeFreeIterations,
38
+ runTimedIterations,
39
+ runTimedIterationsAsync,
40
+ shouldStrictFail,
41
+ toPlainObject,
42
+ tryCompileCase,
43
+ wireInput,
44
+ PersistentExecutable
45
+ } from "../backends/llvm/tests/perf-support.mjs";
46
+
47
+ import {
48
+ cleanName,
49
+ instantiateWasmModule,
50
+ readArenaValue,
51
+ writeValueToArena
52
+ } from "../backends/wasm/tests/perf-support.mjs";
53
+
54
+ import { compileARM64ArtifactFromObject } from "../backends/arm64/src/arm64.mjs";
55
+ import { compileWasmArtifactFromObject } from "../backends/wasm/src/wasm.mjs";
56
+
57
+ // Backend selection
58
+ const backendsEnv = process.env.BACKENDS?.toLowerCase();
59
+ const llvmOnly = process.env.LLVM_ONLY === "1" || backendsEnv === "llvm";
60
+ const wasmOnly = process.env.WASM_ONLY === "1" || backendsEnv === "wasm";
61
+ const arm64Only = process.env.ARM64_ONLY === "1" || backendsEnv === "arm64";
62
+
63
+ const isArm64Host = process.arch === "arm64" && process.platform === "linux";
64
+ const runARM64 = !wasmOnly && !llvmOnly && (isArm64Host || arm64Only);
65
+ const runLLVM = !wasmOnly && !arm64Only;
66
+ const runWasm = !llvmOnly && !arm64Only;
67
+ const runBaselines = !process.env.BACKENDS_ONLY && (process.env.LLVM_ONLY !== "1") && (process.env.WASM_ONLY !== "1") && (process.env.ARM64_ONLY !== "1");
68
+
69
+ const ops = ["plus", "minus", "times"];
70
+ const benchNames = Object.fromEntries(ops.map(op => [op, `bench_${op}`]));
71
+ const inputTexts = csvEnv(
72
+ "INPUTS",
73
+ "11111112222223333334444444555555666666777777788888899999900000011111122222233333344444455555"
74
+ );
75
+ const iterations = parsePositiveIntEnv("ITERATIONS", 3);
76
+
77
+ // ARM64 options
78
+ const arm64WarmupIterations = parseNonNegativeIntEnv("ARM64_WARMUP_ITERATIONS", 1);
79
+ const arm64OptLevel = process.env.ARM64_OPT || "-O2";
80
+
81
+ // LLVM options
82
+ const llvmWarmupIterations = parseNonNegativeIntEnv("LLVM_WARMUP_ITERATIONS", 1);
83
+ const cacheDir = makeCacheDir("k-llvm-int-perf-");
84
+
85
+ // Wasm options
86
+ const wasmWarmupIterations = parseNonNegativeIntEnv("WASM_WARMUP_ITERATIONS", 3);
87
+ const wasmReset = process.env.WASM_RESET !== "0";
88
+ const wasmPipe = process.env.WASM_PIPE === "0" || process.env.WASM_IN_PROCESS === "1" || process.argv.includes("--wasm-in-process")
89
+ ? false
90
+ : true;
91
+ function wasmLaneName() {
92
+ const mode = wasmPipe ? "persistent" : "in-process";
93
+ return `WebAssembly (${mode})`;
94
+ }
95
+
96
+ console.log("==> Initializing state and loading @fraczak/k/Examples/arithmetics.k");
97
+ const state = createState();
98
+ const arithmeticsPath = fileURLToPath(import.meta.resolve("@fraczak/k/Examples/arithmetics.k"));
99
+ await evaluateInput(`:load ${arithmeticsPath}`, state);
100
+
101
+ for (const op of ops) {
102
+ await evaluateInput(`${benchNames[op]} = {inc x, () y} ${op};`, state);
103
+ }
104
+
105
+ function intValue(text) {
106
+ return valueForCode(parseIntValue(text), state.typeAliases.int, codes.find);
107
+ }
108
+
109
+ console.log("==> Preparing relations");
110
+ const relations = {};
111
+ const arithmeticsSource = fs.readFileSync(arithmeticsPath, "utf8");
112
+ const arithmeticsLibrarySource = arithmeticsSource.replace(/\s*\(\)\s*$/, "\n");
113
+ for (const op of ops) {
114
+ const name = benchNames[op];
115
+ relations[op] = prepareRelation(state, name, {
116
+ source: `${arithmeticsLibrarySource}\n${name} = {inc x, () y} ${op};\n${name}`,
117
+ sourceLabel: `@fraczak/k/Examples/arithmetics.k#${name}`
118
+ });
119
+ }
120
+ codes.load(state.codes);
121
+
122
+ console.log("==> Generating test cases and caching expected results");
123
+ const testSuite = [];
124
+ for (const op of ops) {
125
+ for (const inputText of inputTexts) {
126
+ const inputVal = intValue(inputText);
127
+ const relation = relations[op];
128
+
129
+ run.defs = state;
130
+ run_converged.defs = state;
131
+ const expected = run(codes.find, relation.relDef.def, inputVal, relation.relDef.typePatternGraph);
132
+ assert.ok(expected !== undefined, `${op}(${inputText}) should produce a value`);
133
+
134
+ const { inputWire, inputPattern } = wireInput(inputVal);
135
+ testSuite.push({
136
+ op,
137
+ label: inputText,
138
+ inputText,
139
+ inputVal,
140
+ inputWire,
141
+ inputPattern,
142
+ expected
143
+ });
144
+ }
145
+ }
146
+
147
+ // Setup LLVM
148
+ if (runLLVM) {
149
+ console.log("==> Compiling LLVM executables");
150
+ for (const tc of testSuite) {
151
+ const relation = relations[tc.op];
152
+ tc.llvm = tryCompileCase({
153
+ object: relation.object,
154
+ relationName: relation.relationName,
155
+ relHash: relation.relHash,
156
+ inputPattern: tc.inputPattern,
157
+ cacheDir,
158
+ sourceLabel: `@fraczak/k/Examples/arithmetics.k#${relation.relationName}`
159
+ });
160
+ }
161
+ codes.load(state.codes);
162
+ printCompileFailures(testSuite);
163
+ }
164
+
165
+ // Setup Wasm
166
+ let wasmExports = null;
167
+ const wasmExes = new Map();
168
+ if (runWasm) {
169
+ if (wasmPipe) {
170
+ console.log("==> Compiling WebAssembly executables (persistent runner)...");
171
+ for (const op of ops) {
172
+ const relation = relations[op];
173
+ try {
174
+ const wasmPath = path.join(cacheDir, `perf_int_wasm_${op}.wasm`);
175
+ const exePath = path.join(cacheDir, `perf_int_wasm_${op}.exe`);
176
+ const wasmBuf = await compileWasmArtifactFromObject(relation.object, {
177
+ entry: "__main__"
178
+ });
179
+ fs.writeFileSync(wasmPath, wasmBuf);
180
+ const runBin = fileURLToPath(import.meta.resolve("../backends/wasm/bin/k-wasm-run.mjs"));
181
+ fs.writeFileSync(exePath, `#!/bin/sh\nexec node "${runBin}" "${wasmPath}" "$@"\n`, { mode: 0o755 });
182
+ wasmExes.set(op, { status: "ok", exePath, wasmPath });
183
+ } catch (error) {
184
+ wasmExes.set(op, {
185
+ status: "failed",
186
+ error: error.stack || error.message || String(error)
187
+ });
188
+ }
189
+ }
190
+ for (const tc of testSuite) {
191
+ tc.wasm = wasmExes.get(tc.op);
192
+ }
193
+ } else {
194
+ console.log("==> Compiling WebAssembly module...");
195
+ const wabtInstance = await wabtFactory();
196
+ const opHashes = ops.map(op => state.relAliases[benchNames[op]]);
197
+ const wasmModule = await instantiateWasmModule(opHashes, state, wabtInstance);
198
+ wasmExports = wasmModule.exports;
199
+
200
+ for (const tc of testSuite) {
201
+ const relDef = relations[tc.op].relDef;
202
+ const graph = relDef.typePatternGraph;
203
+
204
+ const inputPatternNodeId = graph.find(relDef.def.patterns[0]);
205
+ const inputPattern = propertyListToPattern(patternToPropertyList(exportPatternGraph(graph, inputPatternNodeId)));
206
+
207
+ const outputPatternNodeId = graph.find(relDef.def.patterns[1]);
208
+ const outputPatternPropertyList = patternToPropertyList(exportPatternGraph(graph, outputPatternNodeId));
209
+ const outputPattern = propertyListToPattern(outputPatternPropertyList);
210
+
211
+ tc.wasmPtrIn = writeValueToArena(wasmExports, tc.inputVal, inputPattern, 0);
212
+ tc.wasmOutputPattern = outputPattern;
213
+ tc.wasmOutputPatternPropertyList = outputPatternPropertyList;
214
+ }
215
+ }
216
+ }
217
+
218
+ function createWasmRunner(testSuite) {
219
+ const wasmCases = testSuite.filter(tc => tc.wasm?.status === "ok");
220
+ const servers = new Map();
221
+ function serverFor(exePath) {
222
+ let server = servers.get(exePath);
223
+ if (server == null) {
224
+ server = new PersistentExecutable(exePath);
225
+ servers.set(exePath, server);
226
+ }
227
+ return server;
228
+ }
229
+
230
+ return {
231
+ async run(iterations) {
232
+ if (wasmCases.length === 0) return null;
233
+ return runTimedIterationsAsync(iterations, async () => {
234
+ for (const tc of wasmCases) {
235
+ await serverFor(tc.wasm.exePath).request(tc.inputWire);
236
+ }
237
+ });
238
+ },
239
+ serverFor,
240
+ close() {
241
+ for (const server of servers.values()) server.close();
242
+ }
243
+ };
244
+ }
245
+
246
+ // Setup ARM64
247
+ const arm64Exes = new Map();
248
+ if (runARM64) {
249
+ console.log(`==> Compiling Linux ARM64 executables (${arm64OptLevel})...`);
250
+ for (const op of ops) {
251
+ const relation = relations[op];
252
+ try {
253
+ const exePath = path.join(cacheDir, `perf_int_arm64_${op}`);
254
+ compileARM64ArtifactFromObject(relation.object, {
255
+ entry: "__main__",
256
+ outputPath: exePath,
257
+ optLevel: arm64OptLevel
258
+ });
259
+ arm64Exes.set(op, { status: "ok", exePath });
260
+ } catch (error) {
261
+ arm64Exes.set(op, {
262
+ status: "failed",
263
+ error: error.stack || error.message || String(error)
264
+ });
265
+ }
266
+ }
267
+ for (const tc of testSuite) {
268
+ tc.arm64 = arm64Exes.get(tc.op);
269
+ }
270
+ const failedOps = [...arm64Exes.entries()].filter(([_, v]) => v.status !== "ok");
271
+ if (failedOps.length > 0) {
272
+ console.log("Linux ARM64 compilation failures:");
273
+ for (const [op, res] of failedOps) {
274
+ console.log(` ${op}: ${res.error.split("\n")[0]}`);
275
+ }
276
+ }
277
+ }
278
+
279
+ function printBenchmarkDescription() {
280
+ const lanes = [];
281
+ if (runBaselines) {
282
+ lanes.push("Native JS (Envelope-Aware)");
283
+ lanes.push("Native JS (Envelope-Free)");
284
+ lanes.push("kVM Interpreter (Env-Free)");
285
+ }
286
+ if (runLLVM) lanes.push(llvmLaneName());
287
+ if (runWasm) lanes.push(wasmLaneName());
288
+ if (runARM64) lanes.push(arm64LaneName(arm64OptLevel));
289
+
290
+ console.log("==> Benchmark description");
291
+ console.log(" source: @fraczak/k/Examples/arithmetics.k");
292
+ console.log(` benchmark relations: ${Object.values(benchNames).join(", ")}`);
293
+ console.log(` operations: ${ops.join(", ")}`);
294
+ console.log(` decimal inputs: ${inputTexts.join(", ")}`);
295
+ console.log(` cases: ${testSuite.length} operation/input pairs`);
296
+ if (runLLVM) {
297
+ console.log(` llvm-ready cases: ${testSuite.filter(tc => tc.llvm?.status === "ok").length}`);
298
+ console.log(` llvm warmup iterations: ${llvmWarmupIterations}`);
299
+ }
300
+ if (runWasm) {
301
+ console.log(` wasm runner mode: ${wasmPipe ? "persistent pipe" : "in-process"}`);
302
+ console.log(` wasm warmup iterations: ${wasmWarmupIterations}`);
303
+ if (!wasmPipe) console.log(` wasm arena reset: ${wasmReset ? "yes" : "no"}`);
304
+ }
305
+ if (runARM64) {
306
+ console.log(` arm64-ready cases: ${testSuite.filter(tc => tc.arm64?.status === "ok").length}`);
307
+ console.log(` arm64 warmup iterations: ${arm64WarmupIterations}`);
308
+ console.log(` arm64 opt level: ${arm64OptLevel}`);
309
+ console.log(` arm64 runner mode: ${process.env.ARM64_SPAWN_PER_CALL === "1" ? "spawn per call" : "persistent"}`);
310
+ }
311
+ console.log(` iterations: ${iterations}`);
312
+ console.log(` benchmark lanes: ${lanes.join("; ")}`);
313
+ console.log(" conformance: all outputs are compared to native expected values");
314
+ }
315
+
316
+ printBenchmarkDescription();
317
+ console.log(`==> Running Integer Performance Test (${testSuite.length} cases, Iterations: ${iterations})...`);
318
+
319
+ // 1. Common baseline lanes (only run once!)
320
+ let nativeAwareResult = null;
321
+ let nativeFreeResult = null;
322
+ let kvmFreeResult = null;
323
+
324
+ if (runBaselines) {
325
+ nativeAwareResult = runNativeAwareIterations(iterations, testSuite, relations, state, codes);
326
+ nativeFreeResult = runNativeFreeIterations(iterations, testSuite, relations, state, codes);
327
+ kvmFreeResult = runKVMIterations(iterations, testSuite, relations, state, codes);
328
+ }
329
+
330
+ // 2. LLVM lane
331
+ let llvmResult = null;
332
+ if (runLLVM) {
333
+ const llvmRunner = createLLVMRunner(testSuite);
334
+ try {
335
+ if (llvmWarmupIterations > 0) {
336
+ console.log(`==> Warming LLVM executables (${llvmWarmupIterations} iterations)...`);
337
+ await llvmRunner.run(llvmWarmupIterations);
338
+ }
339
+ llvmResult = await llvmRunner.run(iterations);
340
+ } finally {
341
+ llvmRunner.close();
342
+ }
343
+ }
344
+
345
+ // 3. Wasm lane
346
+ let wasmResult = null;
347
+ if (runWasm) {
348
+ if (wasmPipe) {
349
+ const wasmCases = testSuite.filter(tc => tc.wasm?.status === "ok");
350
+ if (wasmCases.length === testSuite.length) {
351
+ const wasmRunner = createWasmRunner(testSuite);
352
+ try {
353
+ if (wasmWarmupIterations > 0) {
354
+ console.log(`==> Warming WebAssembly (${wasmWarmupIterations} iterations)...`);
355
+ await wasmRunner.run(wasmWarmupIterations);
356
+ }
357
+ console.log(`==> Running WebAssembly (${iterations} iterations)...`);
358
+ wasmResult = await wasmRunner.run(iterations);
359
+ } finally {
360
+ wasmRunner.close();
361
+ }
362
+ }
363
+ } else {
364
+ if (wasmWarmupIterations > 0) {
365
+ console.log(`==> Warming WebAssembly (${wasmWarmupIterations} iterations)...`);
366
+ for (let i = 0; i < wasmWarmupIterations; i++) {
367
+ for (const tc of testSuite) {
368
+ const mark = wasmReset ? wasmExports.arena_mark() : 0;
369
+ const funcName = cleanName(state.relAliases[benchNames[tc.op]]);
370
+ const res = wasmExports[funcName](tc.wasmPtrIn);
371
+ assert.ok(res[1] === 1);
372
+ if (wasmReset) wasmExports.arena_reset(mark);
373
+ }
374
+ }
375
+ }
376
+
377
+ wasmResult = runTimedIterations(iterations, () => {
378
+ for (const tc of testSuite) {
379
+ const mark = wasmReset ? wasmExports.arena_mark() : 0;
380
+ const funcName = cleanName(state.relAliases[benchNames[tc.op]]);
381
+ const res = wasmExports[funcName](tc.wasmPtrIn);
382
+ assert.ok(res[1] === 1);
383
+ if (wasmReset) wasmExports.arena_reset(mark);
384
+ }
385
+ });
386
+ }
387
+ }
388
+
389
+ // 4. Linux ARM64 lane
390
+ let arm64Result = null;
391
+ if (runARM64) {
392
+ const arm64Cases = testSuite.filter(tc => tc.arm64?.status === "ok");
393
+ if (arm64Cases.length === testSuite.length) {
394
+ const arm64Runner = createARM64Runner(testSuite);
395
+ try {
396
+ if (arm64WarmupIterations > 0) {
397
+ console.log(`==> Warming Linux ARM64 (${arm64WarmupIterations} iterations)...`);
398
+ await arm64Runner.run(arm64WarmupIterations);
399
+ }
400
+
401
+ console.log(`==> Running Linux ARM64 (${iterations} iterations)...`);
402
+ arm64Result = await arm64Runner.run(iterations);
403
+ } finally {
404
+ arm64Runner.close();
405
+ }
406
+ }
407
+ }
408
+
409
+ console.log("\n=================== INTEGER BENCHMARK RESULTS ===================");
410
+ console.log(`Operation calls per iteration: ${testSuite.length}`);
411
+ console.log(`Total requested operation calls: ${iterations * testSuite.length}`);
412
+ console.log("-----------------------------------------------------------------");
413
+ let laneIndex = 1;
414
+ if (runBaselines) {
415
+ console.log(`${laneIndex++}. Native JS (Envelope-Aware): ${formatTiming(nativeAwareResult)}`);
416
+ console.log(`${laneIndex++}. Native JS (Envelope-Free): ${formatTiming(nativeFreeResult)}`);
417
+ console.log(`${laneIndex++}. kVM Interpreter (Env-Free): ${formatTiming(kvmFreeResult)}`);
418
+ }
419
+ if (runLLVM) {
420
+ console.log(`${laneIndex++}. ${llvmLaneName().padEnd(29)} ${formatTiming(llvmResult)}`);
421
+ }
422
+ if (runWasm) {
423
+ console.log(`${laneIndex++}. ${wasmLaneName().padEnd(29)} ${formatTiming(wasmResult)}`);
424
+ }
425
+ if (runARM64) {
426
+ const timingStr = arm64Result ? formatTiming(arm64Result) : "compile failed";
427
+ console.log(`${laneIndex++}. ${arm64LaneName(arm64OptLevel).padEnd(29)} ${timingStr}`);
428
+ }
429
+ console.log("=================================================================\n");
430
+
431
+ // Conformance Validation
432
+ for (const tc of testSuite) {
433
+ if (runBaselines) {
434
+ const kvmActual = runKVMCase(tc, relations, state, codes);
435
+ assert.deepEqual(toPlainObject(kvmActual), toPlainObject(tc.expected));
436
+ }
437
+
438
+ if (runLLVM) {
439
+ if (tc.llvm.status !== "ok") {
440
+ tc.llvmConformance = "compile-failed";
441
+ } else {
442
+ try {
443
+ const outputWire = await runExecutable(tc.llvm.exePath, tc.inputWire);
444
+ const actual = decodeWire(outputWire).value;
445
+ assert.deepEqual(toPlainObject(actual), toPlainObject(tc.expected));
446
+ tc.llvmConformance = "ok";
447
+ } catch (error) {
448
+ tc.llvmConformance = "failed";
449
+ tc.llvm.error = error.stack || error.message || String(error);
450
+ console.log(`LLVM conformance failure for ${tc.op}(${tc.label}):`);
451
+ console.log(tc.llvm.error.split("\n").slice(0, 8).join("\n"));
452
+ }
453
+ }
454
+ }
455
+
456
+ if (runWasm) {
457
+ if (wasmPipe) {
458
+ if (tc.wasm?.status !== "ok") {
459
+ tc.wasmConformance = "compile-failed";
460
+ } else {
461
+ try {
462
+ const outputWire = await runExecutable(tc.wasm.exePath, tc.inputWire);
463
+ const actual = decodeWire(outputWire).value;
464
+ assert.deepEqual(toPlainObject(actual), toPlainObject(tc.expected));
465
+ tc.wasmConformance = "ok";
466
+ } catch (error) {
467
+ tc.wasmConformance = "failed";
468
+ tc.wasm.error = error.stack || error.message || String(error);
469
+ console.log(`Wasm conformance failure for ${tc.op}(${tc.label}):`);
470
+ console.log(tc.wasm.error.split("\n").slice(0, 8).join("\n"));
471
+ }
472
+ }
473
+ } else {
474
+ try {
475
+ const funcName = cleanName(state.relAliases[benchNames[tc.op]]);
476
+ const res = wasmExports[funcName](tc.wasmPtrIn);
477
+ assert.ok(res[1] === 1, `Wasm function ${funcName} execution failed`);
478
+ const actual = readArenaValue(
479
+ wasmExports,
480
+ res[0],
481
+ tc.wasmOutputPattern,
482
+ 0,
483
+ tc.wasmOutputPatternPropertyList
484
+ );
485
+ assert.deepEqual(toPlainObject(actual), toPlainObject(tc.expected));
486
+ tc.wasmConformance = "ok";
487
+ } catch (error) {
488
+ tc.wasmConformance = "failed";
489
+ console.log(`Wasm conformance failure for ${tc.op}(${tc.label}):`, error);
490
+ }
491
+ }
492
+ }
493
+
494
+ if (runARM64) {
495
+ if (tc.arm64?.status !== "ok") {
496
+ tc.arm64Conformance = "compile-failed";
497
+ } else {
498
+ try {
499
+ const outputWire = await runExecutable(tc.arm64.exePath, tc.inputWire);
500
+ const actual = decodeWire(outputWire).value;
501
+ assert.deepEqual(toPlainObject(actual), toPlainObject(tc.expected));
502
+ tc.arm64Conformance = "ok";
503
+ } catch (error) {
504
+ tc.arm64Conformance = "failed";
505
+ tc.arm64.error = error.stack || error.message || String(error);
506
+ console.log(`Linux ARM64 conformance failure for ${tc.op}(${tc.label}):`);
507
+ console.log(tc.arm64.error.split("\n").slice(0, 8).join("\n"));
508
+ }
509
+ }
510
+ }
511
+ }
512
+
513
+ const validationSummary = [];
514
+ if (runBaselines) validationSummary.push("kVM");
515
+ if (runLLVM) {
516
+ const llvmOk = testSuite.filter(tc => tc.llvmConformance === "ok").length;
517
+ validationSummary.push(`LLVM ${llvmOk}/${testSuite.length}`);
518
+ }
519
+ if (runWasm) {
520
+ const wasmOk = testSuite.filter(tc => tc.wasmConformance === "ok").length;
521
+ validationSummary.push(`Wasm ${wasmOk}/${testSuite.length}`);
522
+ }
523
+ if (runARM64) {
524
+ const arm64Ok = testSuite.filter(tc => tc.arm64Conformance === "ok").length;
525
+ validationSummary.push(`Linux ARM64 ${arm64Ok}/${testSuite.length}`);
526
+ }
527
+
528
+ console.log(`Conformance validation: ${validationSummary.join(", ")} cases match expected values.`);
529
+ if (runLLVM && shouldStrictFail(testSuite)) process.exitCode = 1;
530
+ if (runWasm && testSuite.some(tc => tc.wasmConformance !== "ok")) process.exitCode = 1;
531
+ if (runARM64 && testSuite.some(tc => tc.arm64Conformance !== "ok")) process.exitCode = 1;