@fraczak/k 7.0.2 → 7.2.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.
- package/CHANGELOG.md +75 -0
- package/DOCS/CODECS.md +37 -2
- package/DOCS/CODEC_ARCHITECTURE.md +12 -5
- package/DOCS/FILE_FORMATS.md +238 -15
- package/DOCS/POLYMORPHIC_IR.md +104 -0
- package/DOCS/REPL.md +11 -3
- package/DOCS/WEB_REPL_REQUIREMENTS.md +1 -1
- package/JOURNAL.md +288 -0
- package/README.md +12 -3
- package/Value.mjs +28 -3
- package/access-table.mjs +343 -0
- package/backend-api.mjs +23 -1
- package/backends/llvm/README.md +20 -21
- package/backends/llvm/bin/k-llvm-build.mjs +105 -32
- package/backends/llvm/bin/k-llvm-compile.mjs +63 -24
- package/backends/llvm/bin/k-llvm.mjs +292 -0
- package/backends/llvm/runtime/krt.c +8 -0
- package/backends/llvm/runtime/krt.h +1 -0
- package/backends/llvm/src/cli.mjs +95 -17
- package/backends/llvm/src/executable.mjs +128 -11
- package/backends/llvm/src/kvm2llvm.mjs +10 -5
- package/backends/llvm/src/llvm.mjs +121 -9
- package/backends/llvm/tests/integration.sh +11 -11
- package/backends/llvm/{bin → tests}/k-llvm-run.mjs +48 -22
- package/backends/llvm/tests/perf-support.mjs +24 -3
- package/backends/llvm/tests/test-llvm.mjs +22 -1
- package/backends/wasm/bin/k-wasm-compile.mjs +46 -20
- package/backends/wasm/bin/k-wasm-run.mjs +61 -20
- package/backends/wasm/bin/k-wasm.mjs +47 -13
- package/backends/wasm/src/cli.mjs +141 -19
- package/backends/wasm/src/wasm.mjs +130 -23
- package/browser/repl-browser.mjs +16 -5
- package/browser/tree-view.mjs +47 -8
- package/browser/vfs-data.mjs +6 -5
- package/codecs/README.md +1 -0
- package/codecs/djson.mjs +270 -0
- package/codecs/int.mjs +2 -1
- package/codecs/json.mjs +7 -2
- package/codecs/k-parse.mjs +36 -9
- package/codecs/k-print.mjs +26 -6
- package/codecs/runtime/codec-sdk.mjs +24 -6
- package/codecs/runtime/pattern-json.mjs +80 -1
- package/codecs/runtime/prefix-codec.mjs +629 -67
- package/codecs/runtime/show-value.mjs +93 -51
- package/codecs/runtime/unicode-string.mjs +29 -6
- package/codecs/show.mjs +24 -6
- package/codecs/utf16.mjs +2 -1
- package/k.mjs +56 -16
- package/kir.mjs +58 -19
- package/kvm.mjs +49 -12
- package/objects/compile.mjs +37 -23
- package/objects/decompile.mjs +40 -10
- package/objects/extract-aliases.mjs +44 -14
- package/objects/inspect.mjs +19 -14
- package/objects/validate.mjs +18 -11
- package/package.json +11 -3
- package/pkir.mjs +772 -0
- package/repl.mjs +92 -23
- package/scripts/build-repl-html.mjs +22 -3
- package/scripts/perf-ieee.mjs +264 -13
- package/scripts/perf-int.mjs +315 -22
- package/scripts/perf-multiplication.mjs +58 -7
- package/scripts/perf-poly.mjs +306 -24
- package/scripts/run-tests.mjs +3 -0
- package/tests/test-access-table.mjs +213 -0
- package/tests/test-codecs.mjs +168 -0
- package/tests/test-pkir.mjs +530 -0
- package/tests/test-polymorphic-tdd.mjs +196 -0
- package/tests/test-repl-html.mjs +16 -2
- package/tests/test-repl.mjs +63 -1
- package/backends/llvm/bin/k-llvm-jit.mjs +0 -160
package/scripts/perf-poly.mjs
CHANGED
|
@@ -62,7 +62,7 @@ function printHelp() {
|
|
|
62
62
|
|
|
63
63
|
Polymorphic List Operations Benchmark Harness.
|
|
64
64
|
Benchmarks reverse, concat, split_by, get_nth, and length on
|
|
65
|
-
Examples/poly.k across Native JS, kVM interpreter, LLVM, and
|
|
65
|
+
Examples/poly.k across Native JS, kVM interpreter, LLVM, Wasm, and PKIR.
|
|
66
66
|
|
|
67
67
|
Options:
|
|
68
68
|
--trace
|
|
@@ -71,16 +71,20 @@ Options:
|
|
|
71
71
|
Enable per-function call count profiling.
|
|
72
72
|
--wasm-in-process
|
|
73
73
|
Run WebAssembly in-process instead of persistent subprocess runner.
|
|
74
|
+
--pkir-only
|
|
75
|
+
Run only PKIR backend.
|
|
74
76
|
-h, --help
|
|
75
77
|
Show this help message and exit.
|
|
76
78
|
|
|
77
79
|
Environment Variables:
|
|
78
80
|
BACKENDS
|
|
79
|
-
Target backend to run: 'llvm' or '
|
|
81
|
+
Target backend to run: 'llvm', 'wasm', or 'pkir'.
|
|
80
82
|
LLVM_ONLY
|
|
81
83
|
Run only LLVM backend ('1' to enable).
|
|
82
84
|
WASM_ONLY
|
|
83
85
|
Run only WebAssembly backend ('1' to enable).
|
|
86
|
+
PKIR_ONLY
|
|
87
|
+
Run only PKIR backend ('1' to enable).
|
|
84
88
|
BACKENDS_ONLY
|
|
85
89
|
Skip JS and kVM interpreter baselines ('1' to enable).
|
|
86
90
|
LIST_LENGTH
|
|
@@ -116,11 +120,52 @@ if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
|
116
120
|
|
|
117
121
|
// Backend selection
|
|
118
122
|
const backendsEnv = process.env.BACKENDS?.toLowerCase();
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
123
|
+
const backendsList = backendsEnv
|
|
124
|
+
? backendsEnv.split(",").map(s => s.trim())
|
|
125
|
+
: null;
|
|
126
|
+
const llvmPkirOnly = process.env.LLVM_PKIR_ONLY === "1"
|
|
127
|
+
|| (backendsList && backendsList.length === 1 &&
|
|
128
|
+
backendsList[0] === "llvm-pkir")
|
|
129
|
+
|| process.argv.includes("--llvm-pkir-only");
|
|
130
|
+
const pkirOnly = !llvmPkirOnly && (
|
|
131
|
+
process.env.PKIR_ONLY === "1"
|
|
132
|
+
|| (backendsList && backendsList.length === 1 &&
|
|
133
|
+
backendsList[0] === "pkir")
|
|
134
|
+
|| process.argv.includes("--pkir-only")
|
|
135
|
+
);
|
|
136
|
+
const llvmOnly = !pkirOnly && !llvmPkirOnly && (
|
|
137
|
+
process.env.LLVM_ONLY === "1"
|
|
138
|
+
|| (backendsList && backendsList.length === 1 &&
|
|
139
|
+
backendsList[0] === "llvm")
|
|
140
|
+
);
|
|
141
|
+
const wasmOnly = !pkirOnly && !llvmPkirOnly && !llvmOnly && (
|
|
142
|
+
process.env.WASM_ONLY === "1"
|
|
143
|
+
|| (backendsList && backendsList.length === 1 &&
|
|
144
|
+
backendsList[0] === "wasm")
|
|
145
|
+
);
|
|
146
|
+
const runLLVM = backendsList
|
|
147
|
+
? backendsList.includes("llvm")
|
|
148
|
+
: !wasmOnly && !pkirOnly && !llvmPkirOnly;
|
|
149
|
+
const runLLVMPKIR = backendsList
|
|
150
|
+
? backendsList.includes("llvm-pkir")
|
|
151
|
+
: !wasmOnly && !pkirOnly && !llvmOnly;
|
|
152
|
+
const runWasm = backendsList
|
|
153
|
+
? backendsList.includes("wasm")
|
|
154
|
+
: !llvmOnly && !pkirOnly && !llvmPkirOnly;
|
|
155
|
+
const runPKIR = backendsList
|
|
156
|
+
? backendsList.includes("pkir")
|
|
157
|
+
: !llvmOnly && !wasmOnly && !llvmPkirOnly;
|
|
158
|
+
const runBaselines = !process.env.BACKENDS_ONLY
|
|
159
|
+
&& (backendsList == null || backendsList.includes("kvm") ||
|
|
160
|
+
backendsList.includes("js"))
|
|
161
|
+
&& !llvmOnly && !wasmOnly && !pkirOnly && !llvmPkirOnly;
|
|
162
|
+
|
|
163
|
+
function llvmLaneNameStr() {
|
|
164
|
+
return llvmLaneName();
|
|
165
|
+
}
|
|
166
|
+
function llvmPkirLaneNameStr() {
|
|
167
|
+
return llvmLaneName().replace("LLVM", "LLVM-PKIR");
|
|
168
|
+
}
|
|
124
169
|
|
|
125
170
|
const ops = ["reverse", "concat", "split_by", "get_nth", "length"];
|
|
126
171
|
const benchNames = Object.fromEntries(ops.map(op => [op, `bench_${op}`]));
|
|
@@ -143,6 +188,9 @@ function wasmLaneName() {
|
|
|
143
188
|
const mode = wasmPipe ? "persistent" : "in-process";
|
|
144
189
|
return `WebAssembly (${mode})`;
|
|
145
190
|
}
|
|
191
|
+
function pkirLaneName() {
|
|
192
|
+
return "PKIR (Wasm persistent)";
|
|
193
|
+
}
|
|
146
194
|
|
|
147
195
|
|
|
148
196
|
console.log("==> Loading @fraczak/k/Examples/arithmetics.k as library");
|
|
@@ -294,13 +342,37 @@ if (runLLVM) {
|
|
|
294
342
|
relHash: relation.relHash,
|
|
295
343
|
inputPattern: tc.inputPattern,
|
|
296
344
|
cacheDir,
|
|
297
|
-
sourceLabel:
|
|
345
|
+
sourceLabel:
|
|
346
|
+
`@fraczak/k/Examples/poly.k#${relation.relationName}`,
|
|
347
|
+
usePKIR: false
|
|
298
348
|
});
|
|
299
349
|
}
|
|
300
350
|
codes.load(state.codes);
|
|
301
351
|
printCompileFailures(testSuite);
|
|
302
352
|
}
|
|
303
353
|
|
|
354
|
+
// Setup LLVM-PKIR
|
|
355
|
+
if (runLLVMPKIR) {
|
|
356
|
+
console.log("==> Compiling LLVM-PKIR executables");
|
|
357
|
+
for (const tc of testSuite) {
|
|
358
|
+
const relation = relations[tc.op];
|
|
359
|
+
tc.llvmPKIR = tryCompileCase({
|
|
360
|
+
object: relation.object,
|
|
361
|
+
relationName: relation.relationName,
|
|
362
|
+
relHash: relation.relHash,
|
|
363
|
+
inputPattern: tc.inputPattern,
|
|
364
|
+
cacheDir,
|
|
365
|
+
sourceLabel:
|
|
366
|
+
`@fraczak/k/Examples/poly.k#${relation.relationName}`,
|
|
367
|
+
usePKIR: true
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
codes.load(state.codes);
|
|
371
|
+
printCompileFailures(
|
|
372
|
+
testSuite.map(tc => ({ ...tc, llvm: tc.llvmPKIR }))
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
304
376
|
// Setup Wasm
|
|
305
377
|
let wasmExports = null;
|
|
306
378
|
let wasmProfileFunctions = [];
|
|
@@ -343,6 +415,34 @@ if (runWasm) {
|
|
|
343
415
|
}
|
|
344
416
|
}
|
|
345
417
|
|
|
418
|
+
// Setup PKIR (persistent runner)
|
|
419
|
+
const pkirExes = new Map();
|
|
420
|
+
if (runPKIR) {
|
|
421
|
+
console.log("==> Compiling PKIR executables (persistent runner)...");
|
|
422
|
+
for (const tc of testSuite) {
|
|
423
|
+
const relation = relations[tc.op];
|
|
424
|
+
try {
|
|
425
|
+
const wasmPath = path.join(cacheDir, `perf_poly_pkir_${tc.op}.wasm`);
|
|
426
|
+
const exePath = path.join(cacheDir, `perf_poly_pkir_${tc.op}.exe`);
|
|
427
|
+
const wasmBuf = await compileWasmArtifactFromObject(relation.object, {
|
|
428
|
+
entry: relation.relHash,
|
|
429
|
+
usePKIR: true
|
|
430
|
+
});
|
|
431
|
+
fs.writeFileSync(wasmPath, wasmBuf);
|
|
432
|
+
const runBin = fileURLToPath(import.meta.resolve("../backends/wasm/bin/k-wasm-run.mjs"));
|
|
433
|
+
fs.writeFileSync(exePath, `#!/bin/sh\nexec node "${runBin}" "${wasmPath}" "$@"\n`, { mode: 0o755 });
|
|
434
|
+
tc.pkir = { status: "ok", exePath, wasmPath };
|
|
435
|
+
pkirExes.set(tc.op, tc.pkir);
|
|
436
|
+
} catch (error) {
|
|
437
|
+
tc.pkir = {
|
|
438
|
+
status: "failed",
|
|
439
|
+
error: error.stack || error.message || String(error)
|
|
440
|
+
};
|
|
441
|
+
pkirExes.set(tc.op, tc.pkir);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
346
446
|
function createWasmRunner(testSuite) {
|
|
347
447
|
const wasmCases = testSuite.filter(tc => tc.wasm?.status === "ok");
|
|
348
448
|
const servers = new Map();
|
|
@@ -371,6 +471,34 @@ function createWasmRunner(testSuite) {
|
|
|
371
471
|
};
|
|
372
472
|
}
|
|
373
473
|
|
|
474
|
+
function createPKIRRunner(testSuite) {
|
|
475
|
+
const pkirCases = testSuite.filter(tc => tc.pkir?.status === "ok");
|
|
476
|
+
const servers = new Map();
|
|
477
|
+
function serverFor(exePath) {
|
|
478
|
+
let server = servers.get(exePath);
|
|
479
|
+
if (server == null) {
|
|
480
|
+
server = new PersistentExecutable(exePath);
|
|
481
|
+
servers.set(exePath, server);
|
|
482
|
+
}
|
|
483
|
+
return server;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return {
|
|
487
|
+
async run(iterations) {
|
|
488
|
+
if (pkirCases.length === 0) return null;
|
|
489
|
+
return runTimedIterationsAsync(iterations, async () => {
|
|
490
|
+
for (const tc of pkirCases) {
|
|
491
|
+
await serverFor(tc.pkir.exePath).request(tc.inputWire);
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
},
|
|
495
|
+
serverFor,
|
|
496
|
+
close() {
|
|
497
|
+
for (const server of servers.values()) server.close();
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
|
|
374
502
|
function printBenchmarkDescription() {
|
|
375
503
|
const lanes = [];
|
|
376
504
|
if (runBaselines) {
|
|
@@ -378,8 +506,10 @@ function printBenchmarkDescription() {
|
|
|
378
506
|
lanes.push("Native JS (Envelope-Free)");
|
|
379
507
|
lanes.push("kVM Interpreter (Env-Free)");
|
|
380
508
|
}
|
|
381
|
-
if (runLLVM) lanes.push(
|
|
509
|
+
if (runLLVM) lanes.push(llvmLaneNameStr());
|
|
510
|
+
if (runLLVMPKIR) lanes.push(llvmPkirLaneNameStr());
|
|
382
511
|
if (runWasm) lanes.push(wasmLaneName());
|
|
512
|
+
if (runPKIR) lanes.push(pkirLaneName());
|
|
383
513
|
|
|
384
514
|
console.log("==> Benchmark description");
|
|
385
515
|
console.log(" source: @fraczak/k/Examples/poly.k");
|
|
@@ -391,11 +521,18 @@ function printBenchmarkDescription() {
|
|
|
391
521
|
console.log(` llvm-ready cases: ${testSuite.filter(tc => tc.llvm?.status === "ok").length}`);
|
|
392
522
|
console.log(` llvm warmup iterations: ${llvmWarmupIterations}`);
|
|
393
523
|
}
|
|
524
|
+
if (runLLVMPKIR) {
|
|
525
|
+
console.log(` llvm-pkir ready cases: ${testSuite.filter(tc => tc.llvmPKIR?.status === "ok").length}`);
|
|
526
|
+
console.log(` llvm-pkir warmup iterations: ${llvmWarmupIterations}`);
|
|
527
|
+
}
|
|
394
528
|
if (runWasm) {
|
|
395
529
|
console.log(` wasm runner mode: ${wasmPipe ? "persistent pipe" : "in-process"}`);
|
|
396
530
|
console.log(` wasm warmup iterations: ${wasmWarmupIterations}`);
|
|
397
531
|
if (!wasmPipe) console.log(` wasm arena reset: ${wasmReset ? "yes" : "no"}`);
|
|
398
532
|
}
|
|
533
|
+
if (runPKIR) {
|
|
534
|
+
console.log(` pkir warmup iterations: ${wasmWarmupIterations}`);
|
|
535
|
+
}
|
|
399
536
|
console.log(` iterations: ${iterations}`);
|
|
400
537
|
console.log(` benchmark lanes: ${lanes.join("; ")}`);
|
|
401
538
|
console.log(" conformance: all outputs are compared to native expected values");
|
|
@@ -431,6 +568,23 @@ if (runLLVM) {
|
|
|
431
568
|
}
|
|
432
569
|
}
|
|
433
570
|
|
|
571
|
+
// 2b. LLVM-PKIR lane
|
|
572
|
+
let llvmPkirResult = null;
|
|
573
|
+
if (runLLVMPKIR) {
|
|
574
|
+
const llvmPkirCases = testSuite.map(tc => ({ ...tc, llvm: tc.llvmPKIR }));
|
|
575
|
+
const llvmPkirRunner = createLLVMRunner(llvmPkirCases);
|
|
576
|
+
try {
|
|
577
|
+
if (llvmWarmupIterations > 0) {
|
|
578
|
+
console.log(`==> Warming LLVM-PKIR executables (${llvmWarmupIterations} iterations)...`);
|
|
579
|
+
await llvmPkirRunner.run(llvmWarmupIterations);
|
|
580
|
+
}
|
|
581
|
+
console.log(`==> Running LLVM-PKIR (${iterations} iterations)...`);
|
|
582
|
+
llvmPkirResult = await llvmPkirRunner.run(iterations);
|
|
583
|
+
} finally {
|
|
584
|
+
llvmPkirRunner.close();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
434
588
|
// 3. Wasm lane
|
|
435
589
|
let wasmResult = null;
|
|
436
590
|
if (runWasm) {
|
|
@@ -476,6 +630,25 @@ if (runWasm) {
|
|
|
476
630
|
}
|
|
477
631
|
}
|
|
478
632
|
|
|
633
|
+
// 4. PKIR lane
|
|
634
|
+
let pkirResult = null;
|
|
635
|
+
if (runPKIR) {
|
|
636
|
+
const pkirCases = testSuite.filter(tc => tc.pkir?.status === "ok");
|
|
637
|
+
if (pkirCases.length === testSuite.length) {
|
|
638
|
+
const pkirRunner = createPKIRRunner(testSuite);
|
|
639
|
+
try {
|
|
640
|
+
if (wasmWarmupIterations > 0) {
|
|
641
|
+
console.log(`==> Warming PKIR (${wasmWarmupIterations} iterations)...`);
|
|
642
|
+
await pkirRunner.run(wasmWarmupIterations);
|
|
643
|
+
}
|
|
644
|
+
console.log(`==> Running PKIR (${iterations} iterations)...`);
|
|
645
|
+
pkirResult = await pkirRunner.run(iterations);
|
|
646
|
+
} finally {
|
|
647
|
+
pkirRunner.close();
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
479
652
|
console.log("\n=================== POLYMORPHIC BENCHMARK RESULTS ===================");
|
|
480
653
|
console.log(`Polymorphic operations per iteration: ${testSuite.length}`);
|
|
481
654
|
console.log(`Total requested operation calls: ${iterations * testSuite.length}`);
|
|
@@ -487,11 +660,19 @@ if (runBaselines) {
|
|
|
487
660
|
console.log(`${laneIndex++}. kVM Interpreter (Env-Free): ${formatTiming(kvmFreeResult)}`);
|
|
488
661
|
}
|
|
489
662
|
if (runLLVM) {
|
|
490
|
-
|
|
663
|
+
const name = llvmLaneNameStr().padEnd(29);
|
|
664
|
+
console.log(`${laneIndex++}. ${name} ${formatTiming(llvmResult)}`);
|
|
665
|
+
}
|
|
666
|
+
if (runLLVMPKIR) {
|
|
667
|
+
const name = llvmPkirLaneNameStr().padEnd(29);
|
|
668
|
+
console.log(`${laneIndex++}. ${name} ${formatTiming(llvmPkirResult)}`);
|
|
491
669
|
}
|
|
492
670
|
if (runWasm) {
|
|
493
671
|
console.log(`${laneIndex++}. ${wasmLaneName().padEnd(29)} ${formatTiming(wasmResult)}`);
|
|
494
672
|
}
|
|
673
|
+
if (runPKIR) {
|
|
674
|
+
console.log(`${laneIndex++}. ${pkirLaneName().padEnd(29)} ${formatTiming(pkirResult)}`);
|
|
675
|
+
}
|
|
495
676
|
console.log("=====================================================================\n");
|
|
496
677
|
|
|
497
678
|
// Conformance Validation
|
|
@@ -518,6 +699,23 @@ for (const tc of testSuite) {
|
|
|
518
699
|
}
|
|
519
700
|
}
|
|
520
701
|
|
|
702
|
+
if (runLLVMPKIR) {
|
|
703
|
+
if (tc.llvmPKIR.status !== "ok") {
|
|
704
|
+
tc.llvmPkirConformance = "compile-failed";
|
|
705
|
+
} else {
|
|
706
|
+
try {
|
|
707
|
+
const outputWire = await runExecutable(tc.llvmPKIR.exePath, tc.inputWire);
|
|
708
|
+
const actual = decodeWire(outputWire).value;
|
|
709
|
+
assert.ok(safeDeepEqual(actual, tc.expected), `LLVM-PKIR output mismatch for ${tc.op}`);
|
|
710
|
+
tc.llvmPkirConformance = "ok";
|
|
711
|
+
} catch (error) {
|
|
712
|
+
tc.llvmPkirConformance = "failed";
|
|
713
|
+
tc.llvmPKIR.error = error.stack || error.message || String(error);
|
|
714
|
+
console.log(`LLVM-PKIR conformance failure for ${tc.op}:`, tc.llvmPKIR.error.split("\n")[0]);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
521
719
|
if (runWasm) {
|
|
522
720
|
if (wasmPipe) {
|
|
523
721
|
if (tc.wasm?.status !== "ok") {
|
|
@@ -557,6 +755,23 @@ for (const tc of testSuite) {
|
|
|
557
755
|
}
|
|
558
756
|
}
|
|
559
757
|
|
|
758
|
+
if (runPKIR) {
|
|
759
|
+
if (tc.pkir?.status !== "ok") {
|
|
760
|
+
tc.pkirConformance = "compile-failed";
|
|
761
|
+
} else {
|
|
762
|
+
try {
|
|
763
|
+
const outputWire = await runExecutable(tc.pkir.exePath, tc.inputWire);
|
|
764
|
+
const actual = decodeWire(outputWire).value;
|
|
765
|
+
assert.ok(safeDeepEqual(actual, tc.expected), `PKIR output mismatch for ${tc.op}`);
|
|
766
|
+
tc.pkirConformance = "ok";
|
|
767
|
+
} catch (error) {
|
|
768
|
+
tc.pkirConformance = "failed";
|
|
769
|
+
tc.pkir.error = error.stack || error.message || String(error);
|
|
770
|
+
console.log(`PKIR conformance failure for ${tc.op}:`, tc.pkir.error.split("\n")[0]);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
560
775
|
}
|
|
561
776
|
|
|
562
777
|
const validationSummary = [];
|
|
@@ -565,14 +780,24 @@ if (runLLVM) {
|
|
|
565
780
|
const llvmOk = testSuite.filter(tc => tc.llvmConformance === "ok").length;
|
|
566
781
|
validationSummary.push(`LLVM ${llvmOk}/${testSuite.length}`);
|
|
567
782
|
}
|
|
783
|
+
if (runLLVMPKIR) {
|
|
784
|
+
const pkirOk = testSuite.filter(tc => tc.llvmPkirConformance === "ok").length;
|
|
785
|
+
validationSummary.push(`LLVM-PKIR ${pkirOk}/${testSuite.length}`);
|
|
786
|
+
}
|
|
568
787
|
if (runWasm) {
|
|
569
788
|
const wasmOk = testSuite.filter(tc => tc.wasmConformance === "ok").length;
|
|
570
789
|
validationSummary.push(`Wasm ${wasmOk}/${testSuite.length}`);
|
|
571
790
|
}
|
|
791
|
+
if (runPKIR) {
|
|
792
|
+
const pkirOk = testSuite.filter(tc => tc.pkirConformance === "ok").length;
|
|
793
|
+
validationSummary.push(`PKIR ${pkirOk}/${testSuite.length}`);
|
|
794
|
+
}
|
|
572
795
|
|
|
573
796
|
console.log(`Conformance validation: ${validationSummary.join(", ")} cases match expected values.`);
|
|
574
797
|
if (runLLVM && shouldStrictFail(testSuite)) process.exitCode = 1;
|
|
798
|
+
if (runLLVMPKIR && shouldStrictFail(testSuite.map(tc => ({ ...tc, llvm: tc.llvmPKIR })))) process.exitCode = 1;
|
|
575
799
|
if (runWasm && testSuite.some(tc => tc.wasmConformance !== "ok")) process.exitCode = 1;
|
|
800
|
+
if (runPKIR && testSuite.some(tc => tc.pkirConformance !== "ok")) process.exitCode = 1;
|
|
576
801
|
|
|
577
802
|
if (runTrace && process.exitCode !== 1) {
|
|
578
803
|
console.log("\n=================== RUNNING MACRO-PHASE TRACING ===================");
|
|
@@ -588,6 +813,18 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
588
813
|
}
|
|
589
814
|
}
|
|
590
815
|
|
|
816
|
+
const llvmPkirServers = new Map();
|
|
817
|
+
if (runLLVMPKIR) {
|
|
818
|
+
for (const tc of testSuite) {
|
|
819
|
+
if (tc.llvmPKIR?.status === "ok") {
|
|
820
|
+
llvmPkirServers.set(
|
|
821
|
+
tc.op,
|
|
822
|
+
new PersistentExecutable(tc.llvmPKIR.exePath)
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
591
828
|
const wasmServers = new Map();
|
|
592
829
|
if (runWasm && wasmPipe) {
|
|
593
830
|
for (const tc of testSuite) {
|
|
@@ -597,6 +834,15 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
597
834
|
}
|
|
598
835
|
}
|
|
599
836
|
|
|
837
|
+
const pkirServers = new Map();
|
|
838
|
+
if (runPKIR) {
|
|
839
|
+
for (const tc of testSuite) {
|
|
840
|
+
if (tc.pkir?.status === "ok") {
|
|
841
|
+
pkirServers.set(tc.op, new PersistentExecutable(tc.pkir.exePath));
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
600
846
|
const averageTrace = (samples) => {
|
|
601
847
|
if (!samples || samples.length === 0) return null;
|
|
602
848
|
const avg = {};
|
|
@@ -641,6 +887,18 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
641
887
|
opData.llvm = averageTrace(samples);
|
|
642
888
|
}
|
|
643
889
|
|
|
890
|
+
// 2b. LLVM-PKIR
|
|
891
|
+
if (llvmPkirServers.has(op)) {
|
|
892
|
+
const server = llvmPkirServers.get(op);
|
|
893
|
+
for (let i = 0; i < 3; i++) await server.requestWithTrace(tc.inputWire);
|
|
894
|
+
const samples = [];
|
|
895
|
+
for (let i = 0; i < sampleReps; i++) {
|
|
896
|
+
const res = await server.requestWithTrace(tc.inputWire);
|
|
897
|
+
if (res.trace) samples.push(res.trace);
|
|
898
|
+
}
|
|
899
|
+
opData.llvmPkir = averageTrace(samples);
|
|
900
|
+
}
|
|
901
|
+
|
|
644
902
|
// 3. Wasm
|
|
645
903
|
if (runWasm) {
|
|
646
904
|
if (wasmPipe) {
|
|
@@ -701,6 +959,18 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
701
959
|
}
|
|
702
960
|
}
|
|
703
961
|
|
|
962
|
+
// PKIR
|
|
963
|
+
if (runPKIR && pkirServers.has(op)) {
|
|
964
|
+
const server = pkirServers.get(op);
|
|
965
|
+
for (let i = 0; i < 3; i++) await server.requestWithTrace(tc.inputWire);
|
|
966
|
+
const samples = [];
|
|
967
|
+
for (let i = 0; i < sampleReps; i++) {
|
|
968
|
+
const res = await server.requestWithTrace(tc.inputWire);
|
|
969
|
+
if (res.trace) samples.push(res.trace);
|
|
970
|
+
}
|
|
971
|
+
opData.pkir = averageTrace(samples);
|
|
972
|
+
}
|
|
973
|
+
|
|
704
974
|
// 4. kVM
|
|
705
975
|
if (runBaselines) {
|
|
706
976
|
const relDef = relations[op].relDef;
|
|
@@ -747,7 +1017,9 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
747
1017
|
}
|
|
748
1018
|
|
|
749
1019
|
for (const s of llvmServers.values()) s.close();
|
|
1020
|
+
for (const s of llvmPkirServers.values()) s.close();
|
|
750
1021
|
for (const s of wasmServers.values()) s.close();
|
|
1022
|
+
for (const s of pkirServers.values()) s.close();
|
|
751
1023
|
|
|
752
1024
|
function formatUs(ns) {
|
|
753
1025
|
if (ns == null || ns === 0) return " - ";
|
|
@@ -766,19 +1038,31 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
766
1038
|
{ name: "Total Request Time", key: "totalNs", isTotal: true }
|
|
767
1039
|
];
|
|
768
1040
|
|
|
1041
|
+
const activeTraceLanes = [];
|
|
1042
|
+
if (runLLVM) {
|
|
1043
|
+
activeTraceLanes.push({ id: "llvm", label: "LLVM" });
|
|
1044
|
+
}
|
|
1045
|
+
if (runLLVMPKIR) {
|
|
1046
|
+
activeTraceLanes.push({ id: "llvmPkir", label: "LLVM-PKIR" });
|
|
1047
|
+
}
|
|
1048
|
+
if (runWasm) activeTraceLanes.push({ id: "wasm", label: "WebAssembly" });
|
|
1049
|
+
if (runPKIR) activeTraceLanes.push({ id: "pkir", label: "PKIR (Wasm)" });
|
|
1050
|
+
if (runBaselines) activeTraceLanes.push({ id: "kvm", label: "kVM Interp" });
|
|
1051
|
+
|
|
1052
|
+
const traceHeader = ["Phase ", ...activeTraceLanes.map(l => l.label.padEnd(13))].join(" | ");
|
|
1053
|
+
const traceDivider = ["------------------------", ...activeTraceLanes.map(() => "-------------")].join("-+-");
|
|
1054
|
+
|
|
769
1055
|
for (const item of phaseResults) {
|
|
770
1056
|
console.log(`\n--- Operation: ${item.op} (${item.label}) ---`);
|
|
771
|
-
console.log(
|
|
772
|
-
console.log(
|
|
1057
|
+
console.log(traceHeader);
|
|
1058
|
+
console.log(traceDivider);
|
|
773
1059
|
for (const phase of phases) {
|
|
774
1060
|
if (phase.isTotal) {
|
|
775
|
-
console.log(
|
|
1061
|
+
console.log(traceDivider);
|
|
776
1062
|
}
|
|
777
1063
|
const pName = phase.name.padEnd(24);
|
|
778
|
-
const
|
|
779
|
-
|
|
780
|
-
const kvmCol = formatUs(item.kvm?.[phase.key]);
|
|
781
|
-
console.log(`${pName} | ${llvmCol} | ${wasmCol} | ${kvmCol}`);
|
|
1064
|
+
const cols = [pName, ...activeTraceLanes.map(l => formatUs(item[l.id]?.[phase.key]))];
|
|
1065
|
+
console.log(cols.join(" | "));
|
|
782
1066
|
}
|
|
783
1067
|
|
|
784
1068
|
const hasProfile = item.wasmProfile || item.kvmProfile;
|
|
@@ -820,11 +1104,11 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
820
1104
|
}
|
|
821
1105
|
|
|
822
1106
|
console.log(`\n=== AVERAGE ACROSS ALL ${phaseResults.length} OPERATIONS ===`);
|
|
823
|
-
console.log(
|
|
824
|
-
console.log(
|
|
1107
|
+
console.log(traceHeader);
|
|
1108
|
+
console.log(traceDivider);
|
|
825
1109
|
for (const phase of phases) {
|
|
826
1110
|
if (phase.isTotal) {
|
|
827
|
-
console.log(
|
|
1111
|
+
console.log(traceDivider);
|
|
828
1112
|
}
|
|
829
1113
|
const pName = phase.name.padEnd(24);
|
|
830
1114
|
const avg = (backend) => {
|
|
@@ -832,10 +1116,8 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
832
1116
|
if (vals.length === 0) return null;
|
|
833
1117
|
return vals.reduce((a, b) => a + b, 0) / vals.length;
|
|
834
1118
|
};
|
|
835
|
-
const
|
|
836
|
-
|
|
837
|
-
const kvmCol = formatUs(avg("kvm"));
|
|
838
|
-
console.log(`${pName} | ${llvmCol} | ${wasmCol} | ${kvmCol}`);
|
|
1119
|
+
const cols = [pName, ...activeTraceLanes.map(l => formatUs(avg(l.id)))];
|
|
1120
|
+
console.log(cols.join(" | "));
|
|
839
1121
|
}
|
|
840
1122
|
|
|
841
1123
|
if (phaseResults.some(r => r.wasmProfile || r.kvmProfile)) {
|
package/scripts/run-tests.mjs
CHANGED
|
@@ -51,6 +51,9 @@ const tests = [
|
|
|
51
51
|
["tests/test-arithmetics.mjs", node, ["tests/test-arithmetics.mjs"]],
|
|
52
52
|
["tests/test-karatsuba.mjs", node, ["tests/test-karatsuba.mjs"]],
|
|
53
53
|
["tests/test-poly.mjs", node, ["tests/test-poly.mjs"]],
|
|
54
|
+
["tests/test-polymorphic-tdd.mjs", node, ["tests/test-polymorphic-tdd.mjs"]],
|
|
55
|
+
["tests/test-access-table.mjs", node, ["tests/test-access-table.mjs"]],
|
|
56
|
+
["tests/test-pkir.mjs", node, ["tests/test-pkir.mjs"]],
|
|
54
57
|
["tests/test-ieee-arithmetic.mjs", node, ["tests/test-ieee-arithmetic.mjs"]],
|
|
55
58
|
["tests/integration.sh", path.join(root, "tests/integration.sh"), []]
|
|
56
59
|
];
|