The function transferSRADebugInfo is modified to include missing cases.
The existing handling produced crash for test case (attached with patch).
Please consider below IR
%struct.BSS1 = type <{ [12 x i8] }> @.BSS1 = internal global %struct.BSS1 zeroinitializer, align 32, !dbg !0, !dbg !7, !dbg !10 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true) !7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_plus_uconst, 4)) !8 = distinct !DIGlobalVariable(name: "nodeb", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true) !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression(DW_OP_plus_uconst, 8)) !11 = distinct !DIGlobalVariable(name: "jmax", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)
In SROA @.BSS1 is broken into @.BSS1.0, @.BSS1.1, @.BSS1.2
@.BSS1.0 = internal unnamed_addr global i32 0, align 32, !dbg !0 @.BSS1.1 = internal unnamed_addr global i32 0, align 32, !dbg !14 @.BSS1.2 = internal unnamed_addr global i32 0, align 8, !dbg !15
Since original memory chunk is broken into three and each fragment directly maps to the three variables "nodea", "nodeb" and "jmax". So below DebugInfo should be generated.
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true) !14 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression()) !8 = distinct !DIGlobalVariable(name: "nodeb", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true) !15 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) !11 = distinct !DIGlobalVariable(name: "jmax", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)
But currently it was wrongly generating DW_OP_LLVM_fragment DIExpression and crashing later.
fragment covers entire variable !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 0, 32)) !1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !10, isLocal: true, isDefinition: true) fragment is larger than or outside of variable !15 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 32, 32)) !1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !10, isLocal: true, isDefinition: true) fragment is larger than or outside of variable !16 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 64, 32)) !1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !10, isLocal: true, isDefinition: true)
Later the verification fails as variable size same as fragment size which should be greater. Which leads a crash.
Breakpoint 2, (anonymous namespace)::Verifier::verifyFragmentExpression<llvm::DIGlobalVariableExpression const> (this=0x7fffffffb790, V=..., Fragment=..., Desc=0x555555712450) at /tmp/llvm-project/llvm/lib/IR/Verifier.cpp:5750 5750 AssertDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V); (gdb) p FragSize != *VarSize $1 = false
Now the function transferSRADebugInfo is modified to
- Ignore the current variable if it starts after the current Fragment
- Ignore the current variable if it ends before the current Fragment
- Generate (!DIExpression()) if current variable completely fits the current Fragment
Otherwise (as earlier), generate the DW_OP_LLVM_fragment in IR if current Fragment partially defines current variable.
nit: can you end each sentence with a . for consistency?