-
Notifications
You must be signed in to change notification settings - Fork 488
Fix #12728: preserve front-end pointer literals during linking #12729
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -389,8 +389,13 @@ IRInst* IRSpecContext::maybeCloneValue(IRInst* originalValue) | |
| case kIROp_PtrLit: | ||
| { | ||
| IRConstant* c = (IRConstant*)originalValue; | ||
| SLANG_RELEASE_ASSERT(c->value.ptrVal == nullptr); | ||
| return builder->getNullPtrValue(cloneType(this, c->getFullType())); | ||
| // Non-null pointer literals are used by front-end-only decorations to retain an AST | ||
| // declaration for diagnostics. Linking stays within the same compiler session, so the | ||
| // declaration remains valid and must be preserved until the mandatory passes consume | ||
| // it. Front-end-only instructions are stripped before target legalization and emit. | ||
| return builder->getPtrValue( | ||
| cloneType(this, c->getFullType()), | ||
| c->value.ptrVal); | ||
|
Comment on lines
+392
to
+398
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n -C 8 \
'IRPrelinkContext|prelinkIR\(|IRSpecContext::maybeCloneValue|kIROp_PtrLit|getPtrValue' \
source/slang
rg -n -C 8 \
'serialize|deserialize|IRPtrLit|kIROp_PtrLit|PtrLit|strip' \
. --glob '*.{cpp,h,hpp,slang}' --glob '!build/**' --glob '!out/**' || trueRepository: shader-slang/slang Length of output: 50375 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- changed branch and cloning callers ---'
sed -n '360,415p' source/slang/slang-ir-link.cpp
sed -n '2440,2605p' source/slang/slang-ir-link.cpp
printf '%s\n' '--- pointer literal definitions and serialization handlers ---'
rg -n -C 12 \
'class IRPtrLit|struct IRPtrLit|IRPtrLit::|getPtrValue\(|kIROp_PtrLit' \
source/slang/slang-ir-insts.h source/slang/slang-ir.cpp source/slang/slang-ir-clone.cpp \
source/slang/slang-serialize-ir.cpp source/slang/slang-serialize-ir.h
printf '%s\n' '--- prelink and module persistence entry points ---'
rg -n -C 10 \
'prelinkIR|Prelink|writeSerializedModuleIR|readSerializedModuleIR|serialize\(.*Module|deserialize' \
source/slang/slang-ir-link.cpp source/slang/slang-serialize-ir.cpp \
source/slang/slang-serialize-container.cpp source/slang/slang-module.cppRepository: shader-slang/slang Length of output: 50374 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- complete prelink flow ---'
sed -n '2594,2725p' source/slang/slang-ir-link.cpp
printf '%s\n' '--- decoration cloning and pointer-literal producers ---'
rg -n -C 16 \
'cloneDecorations\(|addHighLevelDeclDecoration\(|getPtrValue\(' \
source/slang --glob '*.cpp' --glob '*.h'
printf '%s\n' '--- all prelink callers and module serialization callers ---'
rg -n -C 12 \
'prelinkIR\(' source/slang --glob '*.cpp' --glob '*.h'
rg -n -C 12 \
'SerialContainerUtil::write\(|writeSerializedModuleIR\(' source/slang --glob '*.cpp' --glob '*.h'
printf '%s\n' '--- exact IR literal serialization implementation ---'
sed -n '454,520p' source/slang/slang-serialize-ir.cpp
sed -n '521,655p' source/slang/slang-serialize-ir.cppRepository: shader-slang/slang Length of output: 50374 Strip non-null AST pointers before persisting prelinked IR. When 🧰 Tools🪛 GitHub Actions: Check Formatting (comment /format to auto-fix) / 0_check-formatting.txt[error] 393-395: Formatting check failed: clang-format expects the getPtrValue call to be on one line. Run './extras/formatting.sh' or clang-format to fix the formatting. 🪛 GitHub Actions: Check Formatting (comment /format to auto-fix) / check-formatting[error] 393-395: Formatting check failed: clang-format expects the getPtrValue call to be formatted on a single line. Run the formatting script or clang-format to fix this file.
Comment on lines
+396
to
+398
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Gap: changed linking behavior ships with no reachable path and no test In the current tree this new branch is dead: the only producer of a non-null That is a fair reason not to add a test here, but merging behavior that no code path and no test exercises means a later refactor could silently break it (or revert it to the null-assert) with nothing failing in CI. Suggestion: land the regression test together with (or gated on) PR #12691 — a |
||
| } | ||
| break; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Gap: relaxed ptr-lit path drops a hard invariant; comment's correctness argument isn't verifiable, and the guard is removed for the codegen link too
This replaces
SLANG_RELEASE_ASSERT(c->value.ptrVal == nullptr)with a path that forwards any pointer value. The correctness of that now rests entirely on this comment, and two load-bearing invariants are stated abstractly:IRPtrLitreaching this clone path is a front-end-only decoration (in practiceIRHighLevelDeclDecorationviaaddHighLevelDeclDecoration,slang-ir.cpp:7393);Decl*is never dereferenced downstream.Naming the pass that guarantees (2) —
stripFrontEndOnlyInstructions/_shouldStripInstinslang-ir-strip.cpp:18, run ingenerateIRForTranslationUnitbefore serialization/codegen — would let a maintainer verify the lifetime claim without a codebase search.This branch is shared by both
prelinkIR(where the non-null value legitimately occurs, same session, AST alive) and the final codegenlinkIR(which today only sees already-stripped modules). Removing the assert therefore also removes the loud-failure net for the codegen link: if a future front-end-only decoration carrying aDecl*were ever added to the IR but missed by the strip list, a non-nullIRPtrLitwould now be silently propagated into the emitted module (emit backends interpretptrValas a real address) instead of asserting.Suggestion: keep the fix, but consider guarding the invariant rather than dropping it — e.g. a targeted
SLANG_ASSERT/SLANG_RELEASE_ASSERTin the final-codegen (isFinalCodegenLink) case that non-nullIRPtrLitvalues do not reach emit, so an unexpected future producer fails loudly here (per CLAUDE.md "Fail loudly on out-of-contract input" / "assert the invariant"). At minimum, name the strip pass in the comment.