Skip to content

Treat -E/-S/-fsyntax-only as compile-only, not link - #11

Merged
pvelesko merged 7 commits into
mainfrom
fix-preprocess-only-not-link
Jul 29, 2026
Merged

Treat -E/-S/-fsyntax-only as compile-only, not link#11
pvelesko merged 7 commits into
mainfrom
fix-preprocess-only-not-link

Conversation

@pvelesko

Copy link
Copy Markdown
Collaborator

processArgs() set compileOnly for -c/--genco/-dc/-M, but not for -E/-S/-fsyntax-only, so hipcc treated those as link invocations: it appended HIPLDFLAGS (spurious "linker input unused" warnings) and ran the post-link chip-kernel-verify on output that is not a final image.

That crashed on hipcc -E, whose output is a textual offload bundle containing the literal __CLANG_OFFLOAD_BUNDLE__, which the SPIR-V extractor parses as a binary bundle header. Only hosts with ocloc reach it. The existing guard already names -c/-dc/-E/-S in its comment; the parser just never set the flag.

Note: main is 6 commits behind what chipStar already pins (1f2628f), so this PR includes that pre-existing HIPCC_VERIFY series plus the one new commit.

Needed by CHIP-SPV/chipStar#1375.

pvelesko and others added 7 commits April 23, 2026 13:39
After a successful compile, invoke ${HIP_PATH}/bin/chip-kernel-verify on the
output to detect entry points dropped by IGC (intel-graphics-compiler#403).
Env overrides: HIPCC_VERIFY=0 disables, HIPCC_VERIFY=warn prints but never
fails. Default is controlled at build time by HIPCC_VERIFY_DEFAULT from the
parent chipStar CMake.
Without this guard, hipcc invocations during chipStar's own bootstrap build
(when the install tree does not yet contain the verifier) fail with sh exit
code 127, breaking the build. access(X_OK) lets the hook silently no-op when
the binary is absent — running the verifier is best-effort.
-c/-dc/-E/-S outputs carry partial pre-link offload bundles that the SPIR-V
extractor was not designed to parse. Running the verifier on those (CTest:
TestSeparateCompilation, TestRDCWithMultipleHipccCmds, TestStaticLibRDC) was
segfaulting in extractSPIRVModule's bundle-walking path. Final SPIR-V is
produced at link time anyway, so verification on link-final outputs covers
the real surface; verifying intermediates was never meaningful.
processArgs() set compileOnly for -c, --genco, -dc and -M/-MM but not for
-E, -S or -fsyntax-only, so the driver treated those as link invocations.

Two consequences:

  * HIPLDFLAGS were appended, producing spurious "-lCHIP: 'linker' input
    unused" style warnings on every preprocess-only run.

  * The post-link chip-kernel-verify pass ran on non-final output. Its
    guard is written as !opts.compileOnly and its comment already states
    the intent to exclude -c/-dc/-E/-S, but -E and -S never reached it.
    Running the verifier on `hipcc -E` output crashed it: preprocessed
    HIP is a *textual* offload bundle whose delimiter comments contain
    the literal string __CLANG_OFFLOAD_BUNDLE__, which the SPIR-V
    extractor mistakes for the binary bundle magic and then parses ASCII
    as a bundle header.

The crash surfaced only where chip-kernel-verify gets past its ocloc
availability check, i.e. Intel GPU hosts.
@pvelesko
pvelesko merged commit c61296d into main Jul 29, 2026
@pvelesko
pvelesko deleted the fix-preprocess-only-not-link branch July 29, 2026 06:14
pvelesko added a commit to CHIP-SPV/chipStar that referenced this pull request Jul 29, 2026
computeHiprtcCacheKey() keyed on the raw HIP source, so it never saw the
content of headers pulled in by #include, in particular headers resolved
from -I filesystem paths. Editing such a header did not change the key, so
a stale, previously cached SPIR-V was served silently.

When the source may include headers, preprocess it and key on the
preprocessed translation unit. A conservative scan skips the preprocess for
self-contained sources, where the raw source is already a complete key.

Fixing this exposed three latent bugs that had to be resolved for it to
work at all:

  * hipcc never set compileOnly for -E/-S/-fsyntax-only, so it treated them
    as link invocations: it appended link flags and ran the post-link
    chip-kernel-verify pass on output that is not a final image.
    Preprocessed HIP is a *textual* offload bundle whose delimiter comments
    contain the literal __CLANG_OFFLOAD_BUNDLE__, which the SPIR-V
    extractor mistook for the binary bundle magic and then parsed as a
    bundle header, crashing. Only hosts with ocloc got far enough to see
    it, which is why this looked like a compiler bug on the Intel runners.

  * extractSPIRVModule() walked the bundle descriptors using counts and
    sizes read out of the buffer with no bound on the buffer itself. It now
    takes an optional size and rejects out-of-range descriptors, and
    chip-kernel-verify skips textual bundles outright.

  * processOptions() ran only on the cache-miss path, but it is also what
    records "warning: ignored option" in the program log. On a cache hit
    hiprtcGetProgramLog() therefore came back empty, making the log depend
    on cache state (TestHiprtcOptions passed against a cold cache and
    failed on every run after). It is now called once, before the cache
    lookup, which also stops the preprocess pass from logging the same
    warning twice.

Tests: TestHiprtcCacheIncludes asserts that -I header content participates
in the key (miss / hit / miss on edit / hit on revert).
TestHiprtcCacheProgramLog asserts the program log is identical on cache hit
and miss and that diagnostics are not duplicated. Both run through a
wrapper that provisions a guaranteed-empty cache per run.

Requires the HIPCC submodule bump in this commit (CHIP-SPV/HIPCC#11,
now merged to HIPCC main) for the -E/-S fix.

Fixes #1335

Co-authored-by: Paulius Velesko <pvelesko@pglc.io>
pvelesko added a commit to CHIP-SPV/chipStar that referenced this pull request Jul 30, 2026
computeHiprtcCacheKey() keyed on the raw HIP source, so it never saw the
content of headers pulled in by #include, in particular headers resolved
from -I filesystem paths. Editing such a header did not change the key, so
a stale, previously cached SPIR-V was served silently.

When the source may include headers, preprocess it and key on the
preprocessed translation unit. A conservative scan skips the preprocess for
self-contained sources, where the raw source is already a complete key.

Fixing this exposed three latent bugs that had to be resolved for it to
work at all:

  * hipcc never set compileOnly for -E/-S/-fsyntax-only, so it treated them
    as link invocations: it appended link flags and ran the post-link
    chip-kernel-verify pass on output that is not a final image.
    Preprocessed HIP is a *textual* offload bundle whose delimiter comments
    contain the literal __CLANG_OFFLOAD_BUNDLE__, which the SPIR-V
    extractor mistook for the binary bundle magic and then parsed as a
    bundle header, crashing. Only hosts with ocloc got far enough to see
    it, which is why this looked like a compiler bug on the Intel runners.

  * extractSPIRVModule() walked the bundle descriptors using counts and
    sizes read out of the buffer with no bound on the buffer itself. It now
    takes an optional size and rejects out-of-range descriptors, and
    chip-kernel-verify skips textual bundles outright.

  * processOptions() ran only on the cache-miss path, but it is also what
    records "warning: ignored option" in the program log. On a cache hit
    hiprtcGetProgramLog() therefore came back empty, making the log depend
    on cache state (TestHiprtcOptions passed against a cold cache and
    failed on every run after). It is now called once, before the cache
    lookup, which also stops the preprocess pass from logging the same
    warning twice.

Tests: TestHiprtcCacheIncludes asserts that -I header content participates
in the key (miss / hit / miss on edit / hit on revert).
TestHiprtcCacheProgramLog asserts the program log is identical on cache hit
and miss and that diagnostics are not duplicated. Both run through a
wrapper that provisions a guaranteed-empty cache per run.

Requires the HIPCC submodule bump in this commit (CHIP-SPV/HIPCC#11,
now merged to HIPCC main) for the -E/-S fix.

Fixes #1335

Co-authored-by: Paulius Velesko <pvelesko@pglc.io>
pvelesko added a commit to CHIP-SPV/chipStar that referenced this pull request Jul 30, 2026
computeHiprtcCacheKey() keyed on the raw HIP source, so it never saw the
content of headers pulled in by #include, in particular headers resolved
from -I filesystem paths. Editing such a header did not change the key, so
a stale, previously cached SPIR-V was served silently.

When the source may include headers, preprocess it and key on the
preprocessed translation unit. A conservative scan skips the preprocess for
self-contained sources, where the raw source is already a complete key.

Fixing this exposed three latent bugs that had to be resolved for it to
work at all:

  * hipcc never set compileOnly for -E/-S/-fsyntax-only, so it treated them
    as link invocations: it appended link flags and ran the post-link
    chip-kernel-verify pass on output that is not a final image.
    Preprocessed HIP is a *textual* offload bundle whose delimiter comments
    contain the literal __CLANG_OFFLOAD_BUNDLE__, which the SPIR-V
    extractor mistook for the binary bundle magic and then parsed as a
    bundle header, crashing. Only hosts with ocloc got far enough to see
    it, which is why this looked like a compiler bug on the Intel runners.

  * extractSPIRVModule() walked the bundle descriptors using counts and
    sizes read out of the buffer with no bound on the buffer itself. It now
    takes an optional size and rejects out-of-range descriptors, and
    chip-kernel-verify skips textual bundles outright.

  * processOptions() ran only on the cache-miss path, but it is also what
    records "warning: ignored option" in the program log. On a cache hit
    hiprtcGetProgramLog() therefore came back empty, making the log depend
    on cache state (TestHiprtcOptions passed against a cold cache and
    failed on every run after). It is now called once, before the cache
    lookup, which also stops the preprocess pass from logging the same
    warning twice.

Tests: TestHiprtcCacheIncludes asserts that -I header content participates
in the key (miss / hit / miss on edit / hit on revert).
TestHiprtcCacheProgramLog asserts the program log is identical on cache hit
and miss and that diagnostics are not duplicated. Both run through a
wrapper that provisions a guaranteed-empty cache per run.

Requires the HIPCC submodule bump in this commit (CHIP-SPV/HIPCC#11,
now merged to HIPCC main) for the -E/-S fix.

Fixes #1335

Co-authored-by: Paulius Velesko <pvelesko@pglc.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants