From f003bb4d68384e8db506f07808ca9a14c2188ecf Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Mon, 26 Oct 2026 17:58:37 -0500 Subject: [PATCH] Guard by target in the implicit toolchain probe The implicit toolchain probe includes every system header that the runtime and vendored sources spell, under __has_include. clang ships for every target, and through clang 18 including it without the RISC-V vector extension is an #error. Since the vendored zlib's adler32_simd.c spells it, the probe failed with clang 18, which disabled the native cache and program sharding: a sanitized dev build then compiled the whole program as one translation unit. The probe now includes only where __riscv_vector is defined, and the probe's header test covers it and a riscv64 target. --- .../src/backend/native-toolchain.test.ts | 19 +++++++++++++------ .../backend/native/compiler-fingerprint.ts | 7 +++++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/compiler/src/backend/native-toolchain.test.ts b/packages/compiler/src/backend/native-toolchain.test.ts index 1651da083..8fb86d4af 100644 --- a/packages/compiler/src/backend/native-toolchain.test.ts +++ b/packages/compiler/src/backend/native-toolchain.test.ts @@ -630,20 +630,27 @@ test.skipIf(clangExecutable === undefined)( async () => { // clang ships its x86 intrinsic headers (, ...) for every // target, so __has_include finds them on arm64, where including them is - // an #error, and the same holds for the ARM headers on x86. The probe - // must guard them by target. Only the compiler's own freestanding - // headers are visible here, so the result does not depend on the host's - // C library. + // an #error, and the same holds for the ARM headers on x86 and for + // (zlib's RVV code) outside RISC-V with the vector + // extension. The probe must guard them by target. Only the compiler's own + // freestanding headers are visible here, so the result does not depend on + // the host's C library. const includes = (await implicitDependencyProbeIncludes(runtimeSrcDir())).filter( (include) => - include !== "" && /intrin\.h>$|^$|^$/.test(include), + include !== "" && + /intrin\.h>$|^$|^$|^$/.test(include), ); expect(includes).toContain(""); + expect(includes).toContain(""); const resourceDir = execFileSync(clangExecutable!, ["-print-resource-dir"], { encoding: "utf8", }).trim(); const source = includes.map(implicitDependencyIncludeDirective).join(""); - for (const target of ["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"]) { + for (const target of [ + "aarch64-unknown-linux-gnu", + "riscv64-unknown-linux-gnu", + "x86_64-unknown-linux-gnu", + ]) { const result = spawnSync( clangExecutable!, [ diff --git a/packages/compiler/src/backend/native/compiler-fingerprint.ts b/packages/compiler/src/backend/native/compiler-fingerprint.ts index 00d84c09b..4be20a4d0 100644 --- a/packages/compiler/src/backend/native/compiler-fingerprint.ts +++ b/packages/compiler/src/backend/native/compiler-fingerprint.ts @@ -207,7 +207,8 @@ function x86OnlyHeader(include: string): boolean { /** One guarded line of the implicit-toolchain probe source: the header is * included only when the compiler can find it and it belongs to the target - * being probed. */ + * being probed. clang ships for every target, and through + * clang 18 including it without the RISC-V vector extension is an #error. */ export function implicitDependencyIncludeDirective(include: string): string { const targetCondition = x86OnlyHeader(include) ? " && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))" @@ -215,7 +216,9 @@ export function implicitDependencyIncludeDirective(include: string): string { ? " && defined(_WIN32)" : include === "" || include === "" || include === "" ? " && (defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64))" - : ""; + : include === "" + ? " && defined(__riscv_vector)" + : ""; return `#if __has_include(${include})${targetCondition}\n#include ${include}\n#endif\n`; }