mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-25 06:24:27 +08:00
50 lines
2.1 KiB
TypeScript
50 lines
2.1 KiB
TypeScript
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { expect, test } from "vitest";
|
|
import { compile, deserializeModule } from "../src/index.js";
|
|
import { emitLlvmModule } from "../src/backend/llvm/emitter.js";
|
|
|
|
test("array index counters convert to and from numbers with signed conversions on 64-bit targets", async () => {
|
|
const dir = await mkdtemp(join(tmpdir(), "scriptc-integer-induction-"));
|
|
try {
|
|
const entry = join(dir, "main.ts");
|
|
const outPath = join(dir, "main.ir.json");
|
|
const source = `
|
|
function weigh(values: number[]): number {
|
|
let total = 0;
|
|
for (let i = 0; i < values.length; i++) {
|
|
for (let j = i + 1; j < values.length; j++) total += (i / 2) * values[j]! + j;
|
|
}
|
|
return total;
|
|
}
|
|
console.log(weigh([1, 2, 3, 4]));
|
|
`;
|
|
await writeFile(entry, source);
|
|
const result = await compile(entry, { outDir: dir, outPath, outputKind: "ir" });
|
|
if (!result.ok)
|
|
throw new Error(result.diagnostics.map((d) => `${d.code}: ${d.message}`).join("\n"));
|
|
const mod = deserializeModule(await readFile(outPath, "utf8"));
|
|
const body = (ll: string): string =>
|
|
ll.match(
|
|
/define internal [^\n]+ @sc_(?:b)?f_weigh(?:\.i32)?\([^\n]*\) #0 \{([\s\S]*?)\n\}/,
|
|
)![1]!;
|
|
|
|
const wide = body(emitLlvmModule(mod));
|
|
expect(wide).toContain("integer induction");
|
|
// Both counters are read as numbers (i / 2, + j): safe integers, so the
|
|
// signed conversion is exact; the nested start converts back the same way.
|
|
expect(wide).toMatch(/ = sitofp i64 %\w+ to double/);
|
|
expect(wide).not.toMatch(/ = uitofp i64 /);
|
|
expect(wide).toMatch(/ = fptosi double %\w+ to i64/);
|
|
expect(wide).not.toMatch(/ = fptoui double %\w+ to i64/);
|
|
|
|
// 32-bit counters reach 2^32 - 2, beyond the signed i32 range.
|
|
const narrow = body(emitLlvmModule(mod, { pointerBits: 32, wasi: true }));
|
|
expect(narrow).toMatch(/ = uitofp i32 %\w+ to double/);
|
|
expect(narrow).toMatch(/ = fptoui double %\w+ to i32/);
|
|
} finally {
|
|
await rm(dir, { recursive: true, force: true });
|
|
}
|
|
});
|