microsoft / microsoft/DirectXShaderCompiler
[Feature Request][Debug info] Globals lowered to `global.<name>` locals should link to their declaring scope
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 3.7k
- Forks
- 900
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 44
Description
Version: dxcompiler.dll 1.9(5402-0d3ee6b5)(1.9.0.5402) - 1.9.0.5402 (0d3ee6b55-dirty)
Static globals are lowered to SSA values and mirrored into a synthetic
DILocalVariable named global.<name>. That variable is scoped to a function
subprogram and carries no reference to the declaring namespace or class, and no
link back to the DIGlobalVariable that does have the correct scope.
Repro 1: namespace
dxc -T cs_6_0 -Zi -Qembed_debug -Od -Fc namespace_static.ll namespace_static.hlsl
namespace A { static int MyNum = 67; } // line 11
namespace B { static int MyNum = 68; } // line 15
[numthreads(1, 1, 1)]
void main()
{
A::MyNum = input[0];
B::MyNum = input[1];
output[0] = A::MyNum + B::MyNum;
}
Actual
!42 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.MyNum", arg: 0, scope: !4, file: !1, line: 15, type: !12)
!45 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.MyNum", arg: 0, scope: !4, file: !1, line: 11, type: !12)
!4 is the main subprogram for both, so A::MyNum and B::MyNum are
indistinguishable apart from line:.
The namespace is present elsewhere in the module, just not reachable from the
local:
!14 = !DIGlobalVariable(name: "MyNum", linkageName: "\01?MyNum@A@@3HA", scope: !15, file: !1, line: 11, ...)
!15 = !DINamespace(name: "A", scope: null, file: !1, line: 10)
!16 = !DIGlobalVariable(name: "MyNum", linkageName: "\01?MyNum@B@@3HA", scope: !17, file: !1, line: 15, ...)
!17 = !DINamespace(name: "B", scope: null, file: !1, line: 14)
Repro 2: class static member
dxc -T cs_6_0 -Zi -Qembed_debug -Od -Fc class_static_member.ll class_static_member.hlsl
class Counter
{
static int count;
int localValue;
void Initialize(int value) { localValue = value; count += value; }
};
int Counter::count = 0; // line 23
Actual
One global.count is emitted per function that touches the static, each scoped
to that function's subprogram:
!48 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.count", arg: 0, scope: !7, file: !1, line: 23, type: !11)
!51 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.count", arg: 0, scope: !4, file: !1, line: 23, type: !11)
!4 = !DISubprogram(name: "main", ...)
!7 = !DISubprogram(name: "Initialize", linkageName: "\01?Initialize@Counter@@QAAXH@Z", scope: !8, ...)
call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !48, metadata !49), !dbg !50 ; var:"global.count" !DIExpression() func:"Initialize"
call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !51, metadata !49), !dbg !52 ; var:"global.count" !DIExpression() func:"main"
call void @llvm.dbg.value(metadata i32 %6, i64 0, metadata !48, metadata !49), !dbg !50 ; var:"global.count" !DIExpression() func:"Initialize"
call void @llvm.dbg.value(metadata i32 %6, i64 0, metadata !51, metadata !49), !dbg !52 ; var:"global.count" !DIExpression() func:"main"
Expected
There should be a way to link a global lowered to local back to the original global, something like:
!dx.dbg.local_globals = {!100, !101}
!100 = !{ !48, !23 }
!101 = !{ !51, !23 }
!8 = !DICompositeType(tag: DW_TAG_class_type, name: "Counter", file: !1, line: 11, size: 32, align: 32, elements: !9)
!10 = !DIDerivedType(tag: DW_TAG_member, name: "count", scope: !8, file: !1, line: 13, baseType: !11, flags: DIFlagPublic | DIFlagStaticMember)
!23 = !DIGlobalVariable(name: "count", linkageName: "\01?count@Counter@@2HA", scope: !0, file: !1, line: 23, type: !11, isLocal: true, isDefinition: true, declaration: !10)
!48 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.count", arg: 0, scope: !7, file: !1, line: 23, type: !11)
!51 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "global.count", arg: 0, scope: !4, file: !1, line: 23, type: !11)
So the backend can reconstruct the correct scope information if appropriate.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the namespace and class-static cases with the supplied dxc commands, then inspect the generated namespace_static.ll and class_static_member.ll debug metadata. Trace how lowered global values become global. DILocalVariable entries and how the corresponding DIGlobalVariable and declaring scope are represented. Done means the emitted metadata lets the backend recover the namespace or class scope for each lowered local.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100