Repository navigation
Fix missing inlinedAt on localized global debug info - #9052
Marijn Suijten (MarijnS95) wants to merge 2 commits into
Conversation
Since microsoft#7799, PatchDebugInfo() creates a DILocalVariable and dbg.declare for every subprogram on the inlined-at chain of a localized global's users. The declare's location is built from just the global's line and that subprogram as scope, without the inlinedAt the subprogram was inlined at. For any subprogram other than the function itself, that location points at a different subprogram than the function holding the declare, which the LLVM verifier rejects: !dbg attachment points at wrong subprogram for function Later passes propagate the location from those declares onto the dbg.value and dx.op.annotateHandle instructions that replace them, so DXIL with -Zi carries these broken locations for every static global read in an inlined function. Drivers that verify the module, e.g. when linking ray tracing libraries into a state object, print the error for each one. Collect each subprogram together with the location it is inlined at, and give every declare that inlinedAt. A subprogram inlined at several call sites keeps a single variable with one declare per inlined instance, rather than a duplicate variable per call site. Fixes microsoft#8592 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Traverse-Research/DirectXShaderCompiler@49b2b00ff backports microsoft/DirectXShaderCompiler#9052, which gives the debug info that LowerStaticGlobalIntoAlloca creates for static globals in inlined scopes its inlinedAt chain. Without it every static global read in an inlined function carries a !dbg location pointing at the wrong subprogram, and drivers that verify the module flood stderr with "!dbg attachment points at wrong subprogram for function". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Downstream deduplication still drops distinct inline-instance debug bindings, and release-note coverage needs confirmation.
2 open issues
What changed in this PR
Fixes missing inline-call chains in debug information for localized globals, addressing the verifier failures reported in #8592.
Changes:
- Preserves
inlinedAtchains while sharing variable metadata across inline instances. - Adds regression coverage for localized globals and sampler annotations.
| File | Description |
|---|---|
| tools/clang/test/HLSLFileCheck/dxil/debug/local_global_inlined_at.hlsl | Checks inline locations on emitted debug information. |
| lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp | Creates declarations with per-instance inline chains. |
Review effort: Balanced
| DebugLoc Loc = | ||
| DebugLoc::get(DGV->getLine(), 0, Scope, SubprogramAndInlinedAt.second); |
There was a problem hiding this comment.
Added a Bug Fixes entry under Upcoming Release in cf6a7fd.
| DILocalVariable *&ConvertedLocalVar = | ||
| LocalVars[SubprogramAndInlinedAt.first]; | ||
| if (!ConvertedLocalVar) | ||
| ConvertedLocalVar = DIB.createLocalVariable( | ||
| Tag, Scope, Name, DGV->getFile(), DGV->getLine(), Ty); |
There was a problem hiding this comment.
Confirmed: with two call sites only one inlined instance kept its dbg.value, at both -O3 and -Od. Not a regression from this PR (before it, the second call site had no declare at all), but cheap to fix here: cf6a7fd includes the inlinedAt in both LdStHasDebugValue() and DxilDeleteRedundantDebugValues, and the test now has a second call site. It fails without either of the two changes.
The declares PatchDebugInfo() creates for a subprogram inlined at several call sites share one variable and only differ in their inlinedAt. Two passes deduplicating debug values ignored that, and dropped all but one inlined instance's value: - LdStHasDebugValue() skips inserting a dbg.value for a store or load when the instruction right before it is already a dbg.value of the same variable, which is exactly where the previous declare put its. - DxilDeleteRedundantDebugValues erases a dbg.value when another one for the same variable and expression follows it. Include the inlinedAt in both comparisons, and add a second call site to the test, which fails without either change. Also add a release note for microsoft#8592. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Traverse-Research/DirectXShaderCompiler@51ea9903d backports microsoft/DirectXShaderCompiler#9052, which gives the debug info that LowerStaticGlobalIntoAlloca creates for static globals in inlined scopes its inlinedAt chain, and keeps a debug value for every inlined instance of such a global. Without it every static global read in an inlined function carries a !dbg location pointing at the wrong subprogram, and drivers that verify the module flood stderr with "!dbg attachment points at wrong subprogram for function". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
hby (@hbystuff) - wondering if you'd be able to give this a review please? |
|
Thanks Damyan Pepper (@damyanp)! Would you also be able to recommend a reviewer/merger for #8899, which addresses another regression we encountered during this DXC upgrade? |

Since #7799,
PatchDebugInfo()creates adbg.declarefor every subprogram on the inlined-at chain of a localized static global's users, but builds each location with only the global's line and that subprogram as scope, without theinlinedAtit was inlined at. Every such declare in an inlined scope therefore points at a different subprogram than the function holding it, and later passes copy that location onto thedbg.valueanddx.op.annotateHandleinstructions derived from it. The LLVM verifier rejects the result with!dbg attachment points at wrong subprogram for function; drivers that verify the module (e.g. when linking ray tracing libraries into a state object) print that for every static global read in an inlined function.This collects each subprogram together with its
inlinedAtlocation and gives every declare that chain. A subprogram inlined at several call sites keeps one variable, with one declare per inlined instance.Those declares share a variable and only differ in their
inlinedAt, whichLdStHasDebugValue()andDxilDeleteRedundantDebugValuesignored when deduplicating debug values, dropping all but one inlined instance's value. Both now compare theinlinedAttoo.The new test fails without any one of these changes. It deliberately does not pin which subprogram the
annotateHandlelocation is scoped to, because that currently depends on heap layout; #8899 fixes that ordering.Fixes #8592
🤖 Generated with Claude Code