From a8080733dff97efd5da28230a44033396e178d53 Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Sun, 25 Oct 2026 23:42:51 -0500 Subject: [PATCH] Build the bootstrap test's own seed without the function layout The bootstrap test builds its own seed when CI shares none, and that build still applied the committed function layout, so its LLVM listed functions in a different order from the native compiler's own emission. Both seed builds now share one environment, which leaves the layout out. --- scripts/bootstrap-seed.mjs | 23 +++++++++++-------- tests/harness/bootstrap-seed.test.ts | 18 ++++++++++++++- .../self-hosting-native-driver.test.ts | 9 ++------ 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/scripts/bootstrap-seed.mjs b/scripts/bootstrap-seed.mjs index fc9a297d8..6bce075f5 100644 --- a/scripts/bootstrap-seed.mjs +++ b/scripts/bootstrap-seed.mjs @@ -25,6 +25,19 @@ export function verifyBootstrapSeed(directory, revision, sanitize) { } } +/** The environment a bootstrap seed builds with, over the inherited one. The + * bootstrap compares the seed's LLVM with the native compiler's own emission, + * which has no function layout. The layout only orders the functions, so the + * seed is built without it. */ +export function seedBuildEnvironment(sanitize) { + return { + SCRIPTC_SAN: sanitize ? "1" : "", + SCRIPTC_NATIVE_EMIT_IR: "1", + SCRIPTC_NATIVE_OPTIMIZATION: sanitize ? "dev" : "release", + SCRIPTC_NATIVE_LAYOUT: "", + }; +} + async function main() { const directory = process.env.SCRIPTC_BOOTSTRAP_SEED_DIRECTORY; const revision = process.env.GITHUB_SHA; @@ -47,15 +60,7 @@ async function main() { { cwd: root, stdio: "inherit", - env: { - ...process.env, - SCRIPTC_NATIVE_EMIT_IR: "1", - SCRIPTC_NATIVE_OPTIMIZATION: sanitize ? "dev" : "release", - // The bootstrap compares the seed's LLVM with the native compiler's - // own emission, which has no function layout. The layout only orders - // the functions, so the seed is built without it. - SCRIPTC_NATIVE_LAYOUT: "", - }, + env: { ...process.env, ...seedBuildEnvironment(sanitize) }, }, ); writeFileSync( diff --git a/tests/harness/bootstrap-seed.test.ts b/tests/harness/bootstrap-seed.test.ts index 76b1f6de5..2da27baea 100644 --- a/tests/harness/bootstrap-seed.test.ts +++ b/tests/harness/bootstrap-seed.test.ts @@ -3,7 +3,7 @@ import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { load } from "js-yaml"; import { expect, test } from "vitest"; -import { verifyBootstrapSeed } from "../../scripts/bootstrap-seed.mjs"; +import { seedBuildEnvironment, verifyBootstrapSeed } from "../../scripts/bootstrap-seed.mjs"; test("bootstrap artifacts require a complete seed from the same revision, lane, and path", () => { const directory = mkdtempSync(join(tmpdir(), "scriptc-seed-contract-")); @@ -36,6 +36,22 @@ test("bootstrap artifacts require a complete seed from the same revision, lane, } }); +test("seeds build without the function layout in both lanes, shared or not", () => { + for (const sanitize of [false, true]) + expect(seedBuildEnvironment(sanitize)).toEqual({ + SCRIPTC_SAN: sanitize ? "1" : "", + SCRIPTC_NATIVE_EMIT_IR: "1", + SCRIPTC_NATIVE_OPTIMIZATION: sanitize ? "dev" : "release", + SCRIPTC_NATIVE_LAYOUT: "", + }); + // The bootstrap test builds its own seed when CI shares none. + const driver = readFileSync( + new URL("./self-hosting-native-driver.test.ts", import.meta.url), + "utf8", + ); + expect(driver).toContain("...seedBuildEnvironment(sanitize)"); +}); + test("CI restores each seed only into its matching instrumented bootstrap lane", () => { const workflow = load( readFileSync(new URL("../../.github/workflows/ci.yml", import.meta.url), "utf8"), diff --git a/tests/harness/self-hosting-native-driver.test.ts b/tests/harness/self-hosting-native-driver.test.ts index 1cc920bd2..8cfd16eea 100644 --- a/tests/harness/self-hosting-native-driver.test.ts +++ b/tests/harness/self-hosting-native-driver.test.ts @@ -1,4 +1,4 @@ -import { verifyBootstrapSeed } from "../../scripts/bootstrap-seed.mjs"; +import { seedBuildEnvironment, verifyBootstrapSeed } from "../../scripts/bootstrap-seed.mjs"; import { execFile, spawnSync } from "node:child_process"; import { chmodSync, @@ -89,12 +89,7 @@ test( // seed avoids optimizing the huge compiler module before ASan can // exercise its complete traversal, serialization and LLVM emission. ...options, - env: { - ...process.env, - SCRIPTC_SAN: sanitize ? "1" : "", - SCRIPTC_NATIVE_EMIT_IR: "1", - SCRIPTC_NATIVE_OPTIMIZATION: sanitize ? "dev" : "release", - }, + env: { ...process.env, ...seedBuildEnvironment(sanitize) }, }, ), );