mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-30 07:14:39 +08:00
101 lines
3.8 KiB
TypeScript
101 lines
3.8 KiB
TypeScript
import { execFile } from "node:child_process";
|
|
import { createRequire } from "node:module";
|
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
import { dirname, join } from "node:path";
|
|
import { promisify } from "node:util";
|
|
import { expect, test } from "vitest";
|
|
import { hostTargetCpu } from "../../compiler/src/backend/target-cpu.js";
|
|
|
|
const execFileAsync = promisify(execFile);
|
|
const require = createRequire(import.meta.url);
|
|
const repoRoot = join(import.meta.dirname, "../../..");
|
|
const cliEntry = join(repoRoot, "packages/cli/src/main.ts");
|
|
const bootstrapEntry = join(repoRoot, "packages/cli/dist/bootstrap.js");
|
|
const tsxLoader = join(dirname(require.resolve("tsx/package.json")), "dist/loader.mjs");
|
|
const host = hostTargetCpu();
|
|
const runsV3 = host === "x86-64-v3" || host === "x86-64-v4";
|
|
|
|
const program = `const a = new Int32Array(4096);
|
|
for (let i = 0; i < a.length; i++) a[i] = (i * 2654435761) | 0;
|
|
let s = 0;
|
|
for (let r = 0; r < 64; r++) for (let i = 0; i < a.length; i++) s = (s + a[i]!) | 0;
|
|
console.log(s);
|
|
`;
|
|
|
|
test.runIf(process.platform === "linux" && process.arch === "x64")(
|
|
"--target-cpu compiles the program for the level without mixing cache variants",
|
|
async () => {
|
|
const dir = await mkdtemp(join("/tmp", "scriptc-target-cpu-"));
|
|
const entry = join(dir, "main.ts");
|
|
const outPath = join(dir, "program");
|
|
const llvmPath = join(dir, "main.ll");
|
|
const env = { ...process.env, SCRIPTC_CACHE_DIR: join(dir, "cache") };
|
|
const build = async (args: string[], bootstrap = false): Promise<string> => {
|
|
await execFileAsync(
|
|
process.execPath,
|
|
[
|
|
...(bootstrap ? [bootstrapEntry] : ["--import", tsxLoader, cliEntry]),
|
|
"build",
|
|
entry,
|
|
"-o",
|
|
outPath,
|
|
...args,
|
|
],
|
|
{ env, maxBuffer: 4 * 1024 * 1024 },
|
|
);
|
|
return readFile(llvmPath, "utf8");
|
|
};
|
|
try {
|
|
await writeFile(entry, program);
|
|
const expected = `${(await execFileAsync(process.execPath, [entry])).stdout}`;
|
|
const baseline = await build([]);
|
|
expect(baseline).not.toContain('"target-cpu"');
|
|
expect(await build(["--target-cpu=baseline"])).toBe(baseline);
|
|
const v3 = await build(["--target-cpu=x86-64-v3"]);
|
|
expect(v3).toMatch(/^attributes #0 = \{ sanitize_address "target-cpu"="x86-64-v3" \}$/m);
|
|
if (runsV3) expect((await execFileAsync(outPath)).stdout).toBe(expected);
|
|
// The bootstrap's cached route builds without a level.
|
|
expect(await build([], true)).toBe(baseline);
|
|
expect((await execFileAsync(outPath)).stdout).toBe(expected);
|
|
await expect(build(["--target-cpu=haswell"])).rejects.toThrow(/unknown target CPU "haswell"/);
|
|
} finally {
|
|
await rm(dir, { recursive: true, force: true });
|
|
}
|
|
},
|
|
240_000,
|
|
);
|
|
|
|
test("--target-cpu levels are refused for arm64 and WASI targets", async () => {
|
|
const dir = await mkdtemp(join("/tmp", "scriptc-target-cpu-refusal-"));
|
|
const entry = join(dir, "main.ts");
|
|
try {
|
|
await writeFile(entry, program);
|
|
for (const target of ["aarch64-unknown-linux-gnu", "wasm32-wasi"]) {
|
|
for (const kind of ["llvm", "asm", "obj", "exe"]) {
|
|
const build = execFileAsync(
|
|
process.execPath,
|
|
[
|
|
"--import",
|
|
tsxLoader,
|
|
cliEntry,
|
|
"build",
|
|
entry,
|
|
`--emit=${kind}`,
|
|
"-o",
|
|
join(dir, `out-${kind}`),
|
|
"--target-cpu=x86-64-v3",
|
|
],
|
|
{
|
|
env: { ...process.env, SCRIPTC_TARGET: target, SCRIPTC_CACHE_DIR: join(dir, "cache") },
|
|
},
|
|
);
|
|
await expect(build, `${target} ${kind}`).rejects.toThrow(
|
|
/--target-cpu=x86-64-v3 requires an x86-64 target/,
|
|
);
|
|
}
|
|
}
|
|
} finally {
|
|
await rm(dir, { recursive: true, force: true });
|
|
}
|
|
}, 240_000);
|