@fraczak/k 7.0.1 → 7.0.2
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 +36 -0
- package/DOCS/BIG_PICTURE.md +5 -5
- package/DOCS/FILE_FORMATS.md +5 -5
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +9 -9
- package/DOCS/PATTERNS.md +3 -3
- package/DOCS/PROFILING_AND_TRACING.md +60 -72
- package/DOCS/REPL.md +3 -3
- package/DOCS/book/03-types-as-finite-automata.md +4 -4
- package/DOCS/book/06-values-in-memory.md +9 -9
- package/DOCS/book/08-operational-semantics-and-execution.md +1 -1
- package/DOCS/book/09-compiler-architecture.md +2 -2
- package/DOCS/book/10-from-ast-to-intermediate-representation.md +2 -2
- package/DOCS/book/14-canonical-serialization.md +1 -1
- package/Examples/arithmetics.k +2 -2
- package/Examples/bnat.k +1 -1
- package/Examples/karatsuba-mult.k +2 -2
- package/README.md +3 -8
- package/backends/llvm/runtime/krt.c +33 -0
- package/backends/llvm/runtime/krt.h +1 -0
- package/backends/llvm/src/executable.mjs +4 -4
- package/backends/llvm/src/kvm2llvm.mjs +40 -18
- package/backends/llvm/src/llvm.mjs +12 -11
- package/backends/llvm/tests/perf-support.mjs +1 -55
- package/backends/llvm/tests/test-llvm.mjs +3 -3
- package/backends/wasm/src/wasm.mjs +2 -1
- package/backends/wasm/tests/test-wasm.mjs +5 -5
- package/browser/vfs-data.mjs +5 -5
- package/core.k +8 -8
- package/harness/format.mjs +2 -2
- package/harness/registry.mjs +0 -2
- package/kir.mjs +142 -56
- package/package.json +1 -5
- package/scripts/benchmark-idempotency.mjs +12 -8
- package/scripts/benchmark.mjs +5 -9
- package/scripts/build-repl-html.mjs +2 -2
- package/scripts/perf-ieee.mjs +17 -118
- package/scripts/perf-int.mjs +313 -318
- package/scripts/perf-multiplication.mjs +10 -20
- package/scripts/perf-poly.mjs +29 -183
- package/tests/code-derivation/pattern-envelope.mjs +4 -4
- package/tests/test-kvm-polymorphic.mjs +2 -2
- package/backends/arm64/README.md +0 -103
- package/backends/arm64/bin/k-arm64-compile.mjs +0 -93
- package/backends/arm64/bin/k-arm64-run.mjs +0 -58
- package/backends/arm64/bin/k-arm64.mjs +0 -88
- package/backends/arm64/scripts/run-tests.mjs +0 -57
- package/backends/arm64/src/arm64.mjs +0 -229
- package/backends/arm64/src/cli.mjs +0 -155
- package/backends/arm64/src/kvm2arm64.mjs +0 -906
- package/backends/arm64/src/runtime.c +0 -744
- package/backends/arm64/tests/integration.sh +0 -112
- package/backends/arm64/tests/test-arm64.mjs +0 -240
- package/harness/adapters/arm64.mjs +0 -105
package/scripts/perf-ieee.mjs
CHANGED
|
@@ -11,21 +11,19 @@ import {
|
|
|
11
11
|
evaluateInput,
|
|
12
12
|
executeKVM,
|
|
13
13
|
exportPatternGraph,
|
|
14
|
-
parseFloat64,
|
|
15
14
|
patternToPropertyList,
|
|
16
15
|
propertyListToPattern,
|
|
17
16
|
run,
|
|
18
17
|
run_converged,
|
|
19
|
-
valueForCode,
|
|
20
18
|
Value
|
|
21
19
|
} from "@fraczak/k/backend-api.mjs";
|
|
20
|
+
import { parse as parseFloatValue } from "@fraczak/k/codecs/ieee.mjs";
|
|
21
|
+
import { inputPatternForObjectRelation } from "../backends/llvm/src/executable.mjs";
|
|
22
22
|
|
|
23
23
|
import {
|
|
24
24
|
csvEnv,
|
|
25
25
|
formatTiming,
|
|
26
26
|
createLLVMRunner,
|
|
27
|
-
createARM64Runner,
|
|
28
|
-
arm64LaneName,
|
|
29
27
|
llvmLaneName,
|
|
30
28
|
makeCacheDir,
|
|
31
29
|
parseNonNegativeIntEnv,
|
|
@@ -50,14 +48,13 @@ import {
|
|
|
50
48
|
} from "../backends/wasm/tests/perf-support.mjs";
|
|
51
49
|
|
|
52
50
|
import { compileWasmArtifactFromObject } from "../backends/wasm/src/wasm.mjs";
|
|
53
|
-
import { compileARM64ArtifactFromObject } from "../backends/arm64/src/arm64.mjs";
|
|
54
51
|
|
|
55
52
|
function printHelp() {
|
|
56
53
|
console.log(`Usage: node scripts/perf-ieee.mjs [options]
|
|
57
54
|
|
|
58
55
|
IEEE 754 Floating-Point Arithmetic Benchmark Harness.
|
|
59
56
|
Benchmarks add, sub, mul, and div on Examples/ieee.k across
|
|
60
|
-
Native JS, kVM interpreter, LLVM,
|
|
57
|
+
Native JS, kVM interpreter, LLVM, and Wasm backends.
|
|
61
58
|
|
|
62
59
|
Options:
|
|
63
60
|
--opt=<levels>, --opts=<levels>
|
|
@@ -73,13 +70,11 @@ Options:
|
|
|
73
70
|
|
|
74
71
|
Environment Variables:
|
|
75
72
|
BACKENDS
|
|
76
|
-
Target backend to run: 'llvm'
|
|
73
|
+
Target backend to run: 'llvm' or 'wasm'.
|
|
77
74
|
LLVM_ONLY
|
|
78
75
|
Run only LLVM backend ('1' to enable).
|
|
79
76
|
WASM_ONLY
|
|
80
77
|
Run only WebAssembly backend ('1' to enable).
|
|
81
|
-
ARM64_ONLY
|
|
82
|
-
Run only ARM64 backend ('1' to enable).
|
|
83
78
|
BACKENDS_ONLY
|
|
84
79
|
Skip JS and kVM interpreter baselines ('1' to enable).
|
|
85
80
|
VALUES
|
|
@@ -87,14 +82,6 @@ Environment Variables:
|
|
|
87
82
|
(default: 0.5,-4,0,Infinity,-Infinity,NaN).
|
|
88
83
|
ITERATIONS
|
|
89
84
|
Measured iterations per benchmark (default: 3).
|
|
90
|
-
ARM64_WARMUP_ITERATIONS
|
|
91
|
-
Warmup iterations for ARM64 backend (default: 1).
|
|
92
|
-
ARM64_OPT
|
|
93
|
-
ARM64 backend optimization flags (default: -O2).
|
|
94
|
-
ARM64_SPAWN_PER_CALL
|
|
95
|
-
Spawn process per ARM64 call instead of persistent ('1' or '0').
|
|
96
|
-
ARM64_PIPELINE
|
|
97
|
-
Use persistent pipelined runner for ARM64 ('1' or '0').
|
|
98
85
|
LLVM_WARMUP_ITERATIONS
|
|
99
86
|
Warmup iterations for LLVM backend (default: 1).
|
|
100
87
|
LLVM_SPAWN_PER_CALL
|
|
@@ -131,22 +118,14 @@ if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
|
131
118
|
const backendsEnv = process.env.BACKENDS?.toLowerCase();
|
|
132
119
|
const llvmOnly = process.env.LLVM_ONLY === "1" || backendsEnv === "llvm";
|
|
133
120
|
const wasmOnly = process.env.WASM_ONLY === "1" || backendsEnv === "wasm";
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
const runARM64 = !wasmOnly && !llvmOnly && (isArm64Host || arm64Only);
|
|
138
|
-
const runLLVM = !wasmOnly && !arm64Only;
|
|
139
|
-
const runWasm = !llvmOnly && !arm64Only;
|
|
140
|
-
const runBaselines = !process.env.BACKENDS_ONLY && (process.env.LLVM_ONLY !== "1") && (process.env.WASM_ONLY !== "1") && (process.env.ARM64_ONLY !== "1");
|
|
121
|
+
const runLLVM = !wasmOnly;
|
|
122
|
+
const runWasm = !llvmOnly;
|
|
123
|
+
const runBaselines = !process.env.BACKENDS_ONLY && (process.env.LLVM_ONLY !== "1") && (process.env.WASM_ONLY !== "1");
|
|
141
124
|
|
|
142
125
|
const ops = ["add", "sub", "mul", "div"];
|
|
143
126
|
const values = csvEnv("VALUES", "0.5,-4,0,Infinity,-Infinity,NaN");
|
|
144
127
|
const iterations = parsePositiveIntEnv("ITERATIONS", 3);
|
|
145
128
|
|
|
146
|
-
// ARM64 options
|
|
147
|
-
const arm64WarmupIterations = parseNonNegativeIntEnv("ARM64_WARMUP_ITERATIONS", 1);
|
|
148
|
-
const arm64OptLevel = process.env.ARM64_OPT || "-O2";
|
|
149
|
-
|
|
150
129
|
// LLVM options
|
|
151
130
|
const llvmWarmupIterations = parseNonNegativeIntEnv("LLVM_WARMUP_ITERATIONS", 1);
|
|
152
131
|
const llvmRuntimeMode = process.env.K_LLVM_IEEE_RUNTIME_MODE || "fast";
|
|
@@ -200,10 +179,7 @@ const ieeePath = fileURLToPath(import.meta.resolve("@fraczak/k/Examples/ieee.k")
|
|
|
200
179
|
await evaluateInput(`:load ${ieeePath}`, state);
|
|
201
180
|
|
|
202
181
|
function generatePerfK(values) {
|
|
203
|
-
const
|
|
204
|
-
const lines = [
|
|
205
|
-
`$params = {\n${paramFields}\n};`
|
|
206
|
-
];
|
|
182
|
+
const lines = [];
|
|
207
183
|
for (const op of ops) {
|
|
208
184
|
lines.push(`perf_${op} =`);
|
|
209
185
|
lines.push(" {");
|
|
@@ -216,7 +192,7 @@ function generatePerfK(values) {
|
|
|
216
192
|
lines.push(cases.join(",\n"));
|
|
217
193
|
lines.push(" };");
|
|
218
194
|
}
|
|
219
|
-
lines.push("perf_ieee =
|
|
195
|
+
lines.push("perf_ieee =");
|
|
220
196
|
lines.push(" {");
|
|
221
197
|
lines.push(" perf_add add,");
|
|
222
198
|
lines.push(" perf_sub sub,");
|
|
@@ -242,18 +218,16 @@ const relation = prepareRelation(state, "perf_ieee", {
|
|
|
242
218
|
});
|
|
243
219
|
codes.load(state.codes);
|
|
244
220
|
|
|
245
|
-
const float64Hash = state.typeAliases.float64;
|
|
246
|
-
function float64(text) {
|
|
247
|
-
return valueForCode(parseFloat64(text), float64Hash, codes.find);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
221
|
const paramsObj = {};
|
|
251
222
|
for (let i = 0; i < values.length; i++) {
|
|
252
|
-
paramsObj[`p${i}`] =
|
|
223
|
+
paramsObj[`p${i}`] = parseFloatValue(values[i]);
|
|
253
224
|
}
|
|
254
|
-
const
|
|
255
|
-
const
|
|
256
|
-
|
|
225
|
+
const inputVal = Value.product(paramsObj);
|
|
226
|
+
const inferredPattern = inputPatternForObjectRelation(
|
|
227
|
+
relation.object,
|
|
228
|
+
relation.relationName
|
|
229
|
+
);
|
|
230
|
+
const { inputWire, inputPattern } = wireInput(inputVal, inferredPattern);
|
|
257
231
|
|
|
258
232
|
console.log("==> Computing expected results via Native JS");
|
|
259
233
|
run_converged.defs = state;
|
|
@@ -327,39 +301,15 @@ if (runWasm) {
|
|
|
327
301
|
const relDef = relation.relDef;
|
|
328
302
|
const graph = relDef.typePatternGraph;
|
|
329
303
|
|
|
330
|
-
const inputPatternNodeId = graph.find(relDef.def.patterns[0]);
|
|
331
|
-
const inputPat = propertyListToPattern(patternToPropertyList(exportPatternGraph(graph, inputPatternNodeId)));
|
|
332
|
-
|
|
333
304
|
const outputPatternNodeId = graph.find(relDef.def.patterns[1]);
|
|
334
305
|
wasmOutputPatternPropertyList = patternToPropertyList(exportPatternGraph(graph, outputPatternNodeId));
|
|
335
306
|
wasmOutputPattern = propertyListToPattern(wasmOutputPatternPropertyList);
|
|
336
307
|
|
|
337
|
-
wasmPtrIn = writeValueToArena(wasmExports, inputVal,
|
|
308
|
+
wasmPtrIn = writeValueToArena(wasmExports, inputVal, propertyListToPattern(inputPattern), 0);
|
|
338
309
|
wasmFuncName = cleanName(state.relAliases.perf_ieee);
|
|
339
310
|
}
|
|
340
311
|
}
|
|
341
312
|
|
|
342
|
-
// Setup ARM64
|
|
343
|
-
let arm64ExePath = null;
|
|
344
|
-
let arm64CompileError = null;
|
|
345
|
-
|
|
346
|
-
if (runARM64) {
|
|
347
|
-
console.log(`==> Compiling Linux ARM64 executable (${arm64OptLevel})...`);
|
|
348
|
-
try {
|
|
349
|
-
arm64ExePath = path.join(cacheDir, "perf_ieee_arm64");
|
|
350
|
-
compileARM64ArtifactFromObject(relation.object, {
|
|
351
|
-
entry: "__main__",
|
|
352
|
-
inputPattern,
|
|
353
|
-
outputPath: arm64ExePath,
|
|
354
|
-
optLevel: arm64OptLevel
|
|
355
|
-
});
|
|
356
|
-
} catch (error) {
|
|
357
|
-
arm64CompileError = error.stack || error.message || String(error);
|
|
358
|
-
console.log("Linux ARM64 compilation failed:");
|
|
359
|
-
console.log(arm64CompileError.split("\n").slice(0, 8).join("\n"));
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
313
|
function printBenchmarkDescription() {
|
|
364
314
|
const lanes = [];
|
|
365
315
|
if (runBaselines) {
|
|
@@ -374,7 +324,6 @@ function printBenchmarkDescription() {
|
|
|
374
324
|
}
|
|
375
325
|
}
|
|
376
326
|
if (runWasm) lanes.push(wasmLaneName());
|
|
377
|
-
if (runARM64) lanes.push(arm64LaneName(arm64OptLevel));
|
|
378
327
|
|
|
379
328
|
console.log("==> Benchmark description");
|
|
380
329
|
console.log(" source: @fraczak/k/Examples/ieee.k#perf_ieee (single program)");
|
|
@@ -394,11 +343,6 @@ function printBenchmarkDescription() {
|
|
|
394
343
|
console.log(` wasm arena reset: ${wasmReset ? "yes" : "no"}`);
|
|
395
344
|
}
|
|
396
345
|
}
|
|
397
|
-
if (runARM64) {
|
|
398
|
-
console.log(` arm64 warmup iterations: ${arm64WarmupIterations}`);
|
|
399
|
-
console.log(` arm64 opt level: ${arm64OptLevel}`);
|
|
400
|
-
console.log(` arm64 runner mode: ${process.env.ARM64_SPAWN_PER_CALL === "1" ? "spawn per call" : "persistent"}`);
|
|
401
|
-
}
|
|
402
346
|
console.log(` iterations: ${iterations}`);
|
|
403
347
|
console.log(` benchmark lanes: ${lanes.join("; ")}`);
|
|
404
348
|
console.log(" conformance: all outputs are compared to native expected values");
|
|
@@ -501,27 +445,6 @@ if (runWasm) {
|
|
|
501
445
|
}
|
|
502
446
|
}
|
|
503
447
|
|
|
504
|
-
// 4. Linux ARM64 lane
|
|
505
|
-
let arm64Result = null;
|
|
506
|
-
if (runARM64 && arm64ExePath) {
|
|
507
|
-
const arm64Runner = createARM64Runner([{
|
|
508
|
-
op: "perf_ieee",
|
|
509
|
-
inputWire,
|
|
510
|
-
arm64: { status: "ok", exePath: arm64ExePath }
|
|
511
|
-
}]);
|
|
512
|
-
try {
|
|
513
|
-
if (arm64WarmupIterations > 0) {
|
|
514
|
-
console.log(`==> Warming Linux ARM64 (${arm64WarmupIterations} iterations)...`);
|
|
515
|
-
await arm64Runner.run(arm64WarmupIterations);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
console.log(`==> Running Linux ARM64 (${iterations} iterations)...`);
|
|
519
|
-
arm64Result = await arm64Runner.run(iterations);
|
|
520
|
-
} finally {
|
|
521
|
-
arm64Runner.close();
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
|
|
525
448
|
console.log("\n=================== IEEE BENCHMARK RESULTS ===================");
|
|
526
449
|
console.log(`Program calls per iteration: 1 (${totalOps} IEEE operations evaluated inside)`);
|
|
527
450
|
console.log(`Total requested program calls: ${iterations} (${iterations * totalOps} equivalent IEEE operations)`);
|
|
@@ -544,10 +467,6 @@ if (runWasm) {
|
|
|
544
467
|
const timingStr = wasmResult ? formatTiming(wasmResult) : "compile failed";
|
|
545
468
|
console.log(`${laneIndex++}. ${wasmLaneName().padEnd(29)} ${timingStr}`);
|
|
546
469
|
}
|
|
547
|
-
if (runARM64) {
|
|
548
|
-
const timingStr = arm64Result ? formatTiming(arm64Result) : "compile failed";
|
|
549
|
-
console.log(`${laneIndex++}. ${arm64LaneName(arm64OptLevel).padEnd(29)} ${timingStr}`);
|
|
550
|
-
}
|
|
551
470
|
console.log("==============================================================\n");
|
|
552
471
|
|
|
553
472
|
// Conformance Validation
|
|
@@ -621,22 +540,6 @@ if (runWasm) {
|
|
|
621
540
|
}
|
|
622
541
|
}
|
|
623
542
|
|
|
624
|
-
let arm64Ok = false;
|
|
625
|
-
if (runARM64) {
|
|
626
|
-
if (!arm64ExePath) {
|
|
627
|
-
console.log("Linux ARM64 conformance failure: executable was not compiled");
|
|
628
|
-
} else {
|
|
629
|
-
try {
|
|
630
|
-
const outputWire = await runExecutable(arm64ExePath, inputWire);
|
|
631
|
-
const actual = decodeWire(outputWire).value;
|
|
632
|
-
assert.deepEqual(toPlainObject(actual), toPlainObject(expected));
|
|
633
|
-
arm64Ok = true;
|
|
634
|
-
} catch (error) {
|
|
635
|
-
console.log("Linux ARM64 conformance failure:", error.message || error);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
|
|
640
543
|
const validationSummary = [];
|
|
641
544
|
if (runBaselines && kvmOk) validationSummary.push(`kVM (all ${totalOps} ops)`);
|
|
642
545
|
if (runLLVM) {
|
|
@@ -649,9 +552,6 @@ if (runLLVM) {
|
|
|
649
552
|
if (runWasm) {
|
|
650
553
|
validationSummary.push(`Wasm (${wasmOk ? `all ${totalOps} ops` : "failed"})`);
|
|
651
554
|
}
|
|
652
|
-
if (runARM64) {
|
|
653
|
-
validationSummary.push(`Linux ARM64 (${arm64Ok ? `all ${totalOps} ops` : "failed"})`);
|
|
654
|
-
}
|
|
655
555
|
|
|
656
556
|
console.log(`Conformance validation: ${validationSummary.join(", ")} match expected values.`);
|
|
657
557
|
if (runLLVM) {
|
|
@@ -661,4 +561,3 @@ if (runLLVM) {
|
|
|
661
561
|
}
|
|
662
562
|
}
|
|
663
563
|
if (runWasm && !wasmOk) process.exitCode = 1;
|
|
664
|
-
if (runARM64 && !arm64Ok) process.exitCode = 1;
|