Skip to content

Commit e39e2b4

Browse files
committed
[DebugInfo] Prevent invalid fragments at ISel from dropping debug info
During SelectionDAG, if a value which is associated with a DBG_VALUE needs to be split across multiple registers, the DBG_VALUE will be split into a set of fragment expressions to recreate the original value. If one or more of these fragments cannot be created, they would previously be silently dropped, causing the old debug value to live past its expiry date. This patch fixes this issue by keeping invalid fragments while setting their value as Undef. Differential revision: https://reviews.llvm.org/D70248
1 parent f70f180 commit e39e2b4

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5553,8 +5553,14 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
55535553
for (auto RegAndSize : SplitRegs) {
55545554
auto FragmentExpr = DIExpression::createFragmentExpression(
55555555
Expr, Offset, RegAndSize.second);
5556-
if (!FragmentExpr)
5556+
// If a valid fragment expression cannot be created, the variable's
5557+
// correct value cannot be determined and so it is set as Undef.
5558+
if (!FragmentExpr) {
5559+
SDDbgValue *SDV = DAG.getConstantDbgValue(
5560+
Variable, Expr, UndefValue::get(V->getType()), DL, SDNodeOrder);
5561+
DAG.AddDbgValue(SDV, nullptr, false);
55575562
continue;
5563+
}
55585564
assert(!IsDbgDeclare && "DbgDeclare operand is not in memory?");
55595565
FuncInfo.ArgDbgValues.push_back(
55605566
BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), false,
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
; RUN: llc < %s -mtriple=armv7-linux-gnueabihf -stop-before=finalize-isel | FileCheck %s
2+
3+
; When splitting-up integers during CodeGen, if the debug info contains
4+
; an expression with carry operators (i.e. arithmetic and shift ops), the
5+
; debug information will be dropped as these operators cannot be correctly
6+
; expressed across different registers.
7+
8+
; CHECK: [[HIGH:![0-9]+]] = !DILocalVariable(name: "high"
9+
; CHECK: [[LOW:![0-9]+]] = !DILocalVariable(name: "low"
10+
;
11+
; As the debug information for "high" contains an arithmetic shift, while for
12+
; "low" it does not, only the former should be undefined.
13+
; CHECK-LABEL: body:
14+
; CHECK: [[LOWR:%[0-9]+]]:gpr = COPY $r0
15+
; CHECK: DBG_VALUE [[LOWR]], $noreg, [[LOW]]
16+
; CHECK: DBG_VALUE $noreg, $noreg, [[HIGH]]
17+
; CHECK: DBG_VALUE $noreg, $noreg, [[HIGH]]
18+
19+
define dso_local i64 @_Z2fnx(i64 returned %value) local_unnamed_addr !dbg !7 {
20+
entry:
21+
call void @llvm.dbg.value(metadata i64 %value, metadata !13, metadata !DIExpression()), !dbg !17
22+
call void @llvm.dbg.value(metadata i64 %value, metadata !14, metadata !DIExpression(DW_OP_constu, 32, DW_OP_shra, DW_OP_LLVM_convert, 64, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !17
23+
call void @llvm.dbg.value(metadata i64 %value, metadata !16, metadata !DIExpression(DW_OP_LLVM_convert, 64, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value)), !dbg !17
24+
ret i64 %value, !dbg !18
25+
}
26+
27+
declare void @llvm.dbg.value(metadata, metadata, metadata)
28+
29+
!llvm.dbg.cu = !{!0}
30+
!llvm.module.flags = !{!3, !4, !5}
31+
!llvm.ident = !{!6}
32+
33+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
34+
!1 = !DIFile(filename: "test.cpp", directory: "/tmp")
35+
!2 = !{}
36+
!3 = !{i32 2, !"Dwarf Version", i32 4}
37+
!4 = !{i32 2, !"Debug Info Version", i32 3}
38+
!5 = !{i32 1, !"wchar_size", i32 4}
39+
!6 = !{!"clang version 10.0.0"}
40+
!7 = distinct !DISubprogram(name: "fn", linkageName: "_Z2fnx", scope: !8, file: !8, line: 2, type: !9, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
41+
!8 = !DIFile(filename: "test.cpp", directory: "/tmp")
42+
!9 = !DISubroutineType(types: !10)
43+
!10 = !{!11, !11}
44+
!11 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)
45+
!12 = !{!13, !14, !16}
46+
!13 = !DILocalVariable(name: "value", arg: 1, scope: !7, file: !8, line: 2, type: !11)
47+
!14 = !DILocalVariable(name: "high", scope: !7, file: !8, line: 3, type: !15)
48+
!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
49+
!16 = !DILocalVariable(name: "low", scope: !7, file: !8, line: 4, type: !15)
50+
!17 = !DILocation(line: 0, scope: !7)
51+
!18 = !DILocation(line: 5, column: 3, scope: !7)

0 commit comments

Comments
 (0)