llvm.org GIT mirror llvm / 11a3cfb
DwarfDebug: Support floating point constants in location lists. This patch closes a gap in the DWARF backend that caused LLVM to drop debug info for floating point variables that were constant for part of their scope. Floating point constants are emitted as one or more DW_OP_constu joined via DW_OP_piece. This fixes a regression caught by the LLDB testsuite that I introduced in r262247 when we stopped blindly expanding the range of singular DBG_VALUEs to span the entire scope and started to emit location lists with accurate ranges instead. Also deletes a now-impossible testcase (debug-loc-empty-entries). <rdar://problem/25448338> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265760 91177308-0d34-0410-b5e6-96231b3b80d8 Adrian Prantl 4 years ago
5 changed file(s) with 128 addition(s) and 85 deletion(s). Raw diff Collapse all Expand all
14371437 DwarfExpr.AddMachineRegExpression(Expr, Loc.getReg(),
14381438 PieceOffsetInBits);
14391439 }
1440 }
1441 // else ... ignore constant fp. There is not any good way to
1442 // to represent them here in dwarf.
1443 // FIXME: ^
1440 } else if (Value.isConstantFP()) {
1441 APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
1442 DwarfExpr.AddUnsignedConstant(RawBytes);
1443 }
14441444 }
14451445
14461446 void DebugLocEntry::finalize(const AsmPrinter &AP,
158158 return CurPos > PieceOffsetInBits;
159159 }
160160
161 void DwarfExpression::AddStackValue() {
162 if (DwarfVersion >= 4)
163 EmitOp(dwarf::DW_OP_stack_value);
164 }
165
161166 void DwarfExpression::AddSignedConstant(int Value) {
162167 EmitOp(dwarf::DW_OP_consts);
163168 EmitSigned(Value);
164 // The proper way to describe a constant value is
165 // DW_OP_constu , DW_OP_stack_value.
166 // Unfortunately, DW_OP_stack_value was not available until DWARF-4,
167 // so we will continue to generate DW_OP_constu for DWARF-2
168 // and DWARF-3. Technically, this is incorrect since DW_OP_const
169 // actually describes a value at a constant addess, not a constant value.
170 // However, in the past there was no better way to describe a constant
171 // value, so the producers and consumers started to rely on heuristics
172 // to disambiguate the value vs. location status of the expression.
173 // See PR21176 for more details.
174 if (DwarfVersion >= 4)
175 EmitOp(dwarf::DW_OP_stack_value);
169 AddStackValue();
176170 }
177171
178172 void DwarfExpression::AddUnsignedConstant(unsigned Value) {
179173 EmitOp(dwarf::DW_OP_constu);
180174 EmitUnsigned(Value);
181 // cf. comment in DwarfExpression::AddSignedConstant().
182 if (DwarfVersion >= 4)
183 EmitOp(dwarf::DW_OP_stack_value);
175 AddStackValue();
176 }
177
178 void DwarfExpression::AddUnsignedConstant(APInt Value) {
179 unsigned Size = Value.getBitWidth();
180 const uint64_t *Data = Value.getRawData();
181
182 // Chop it up into 64-bit pieces, because that's the maximum that
183 // AddUnsignedConstant takes.
184 unsigned Offset = 0;
185 while (Offset < Size) {
186 AddUnsignedConstant(*Data++);
187 if (Offset == 0 && Size <= 64)
188 break;
189 AddOpPiece(std::min(Size-Offset, 64u), Offset);
190 Offset += 64;
191 }
184192 }
185193
186194 static unsigned getOffsetOrZero(unsigned OffsetInBits,
6060 void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
6161 /// Emit a shift-right dwarf expression.
6262 void AddShr(unsigned ShiftBy);
63 /// Emit a DW_OP_stack_value, if supported.
64 ///
65 /// The proper way to describe a constant value is
66 /// DW_OP_constu , DW_OP_stack_value.
67 /// Unfortunately, DW_OP_stack_value was not available until DWARF-4,
68 /// so we will continue to generate DW_OP_constu for DWARF-2
69 /// and DWARF-3. Technically, this is incorrect since DW_OP_const
70 /// actually describes a value at a constant addess, not a constant value.
71 /// However, in the past there was no better way to describe a constant
72 /// value, so the producers and consumers started to rely on heuristics
73 /// to disambiguate the value vs. location status of the expression.
74 /// See PR21176 for more details.
75 void AddStackValue();
6376
6477 /// Emit an indirect dwarf register operation for the given machine register.
6578 /// \return false if no DWARF register exists for MachineReg.
8699 void AddSignedConstant(int Value);
87100 /// Emit an unsigned constant.
88101 void AddUnsignedConstant(unsigned Value);
102 /// Emit an unsigned constant.
103 void AddUnsignedConstant(APInt Value);
89104
90105 /// \brief Emit an entire expression on top of a machine register location.
91106 ///
+0
-66
test/DebugInfo/X86/debug-loc-empty-entries.ll less more
None ; RUN: llc -mtriple=x86_64-apple-macosx <%s | FileCheck %s
1 ; Test that we don't generate empty .debug_loc entries. Originally, there were
2 ; two empty .debug_loc entries for 'a' in an otherwise empty .debug_loc list.
3 ;
4 ; CHECK: .section __DWARF,__debug_loc,regular,debug
5 ; CHECK-NEXT: Lsection_debug_loc:
6 ; CHECK-NEXT: .section __DWARF,__debug_abbrev,regular,debug
7 ;
8 ; Test that the variable stuck around.
9 ; CHECK: .section __DWARF,__debug_info,regular,debug
10 ; CHECK: DW_TAG_variable
11 ; CHECK-NOT: DW_AT_location
12
13 ; Generated using clang -cc1 with the following args:
14 ;
15 ; -triple x86_64-apple-macosx -emit-llvm -gdwarf-4 -O1
16 ;
17 ; From this testcase:
18 ;
19 ;; void fn1() {
20 ;; float a = 1;
21 ;; for (;;)
22 ;; a = 0;
23 ;; }
24
25 ; Function Attrs: noreturn nounwind readnone
26 define void @_Z3fn1v() #0 !dbg !4 {
27 entry:
28 tail call void @llvm.dbg.value(metadata float 1.000000e+00, i64 0, metadata !9, metadata !14), !dbg !15
29 br label %for.cond, !dbg !16
30
31 for.cond: ; preds = %for.cond, %entry
32 tail call void @llvm.dbg.value(metadata float 0.000000e+00, i64 0, metadata !9, metadata !14), !dbg !15
33 br label %for.cond, !dbg !17
34 }
35
36 ; Function Attrs: nounwind readnone
37 declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
38
39 attributes #0 = { noreturn nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
40 attributes #1 = { nounwind readnone }
41
42 !llvm.dbg.cu = !{!0}
43 !llvm.module.flags = !{!11, !12}
44 !llvm.ident = !{!13}
45
46 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.7.0 (trunk 238517) (llvm/trunk 238524)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2)
47 !1 = !DIFile(filename: "", directory: "/Users/dexonsmith/data/llvm/bootstrap/play/delta2/testcase")
48 !2 = !{}
49 !3 = !{!4}
50 !4 = distinct !DISubprogram(name: "fn1", linkageName: "_Z3fn1v", scope: !5, file: !5, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, variables: !8)
51 !5 = !DIFile(filename: "t.cpp", directory: "/Users/dexonsmith/data/llvm/bootstrap/play/delta2/testcase")
52 !6 = !DISubroutineType(types: !7)
53 !7 = !{null}
54 !8 = !{!9}
55 !9 = !DILocalVariable(name: "a", scope: !4, file: !5, line: 2, type: !10)
56 !10 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float)
57 !11 = !{i32 2, !"Dwarf Version", i32 4}
58 !12 = !{i32 2, !"Debug Info Version", i32 3}
59 !13 = !{!"clang version 3.7.0 (trunk 238517) (llvm/trunk 238524)"}
60 !14 = !DIExpression()
61 !15 = !DILocation(line: 2, scope: !4)
62 !16 = !DILocation(line: 3, scope: !4)
63 !17 = !DILocation(line: 3, scope: !18)
64 !18 = distinct !DILexicalBlock(scope: !19, file: !5, line: 3)
65 !19 = distinct !DILexicalBlock(scope: !4, file: !5, line: 3)
0 ; RUN: llc %s -stop-after=livedebugvalues -o %t 2>&1 | FileCheck --check-prefix=SANITY %s
1 ; RUN: llc < %s -filetype=obj | llvm-dwarfdump - | FileCheck %s
2 ; Test debug_loc support for floating point constants.
3 ;
4 ; Created from clang -O1:
5 ; void barrier();
6 ; void foo() {
7 ; float f;
8 ; long double ld;
9 ; barrier();
10 ; f = 3.14;
11 ; ld = 3.14;
12 ; barrier();
13 ; }
14 ;
15 ; SANITY: CALL{{.*}} @barrier
16 ; SANITY: DBG_VALUE x86_fp80 0xK4000C8F5C28F5C28F800
17 ; SANITY: DBG_VALUE float 0x40091EB860000000
18 ; SANITY: TAILJMP{{.*}} @barrier
19 ;
20 ; CHECK: .debug_info contents:
21 ; CHECK: DW_TAG_variable
22 ; CHECK-NEXT: DW_AT_location {{.*}} (0x00000000)
23 ; CHECK-NEXT: DW_AT_name {{.*}}"ld"
24 ; CHECK: DW_TAG_variable
25 ; CHECK-NEXT: DW_AT_location {{.*}} (0x00000031)
26 ; CHECK-NEXT: DW_AT_name {{.*}}"f"
27 ;
28 ; CHECK: .debug_loc contents:
29 ; CHECK: 0x00000000: Beginning address offset: [[START:.*]]
30 ; CHECK: Ending address offset: [[END:.*]]
31 ; CHECK: Location description: 10 80 f0 a3 e1 05 93 08 10 80 80 01 9d 10 40
32 ; constu ..., piece 8, constu ..., bit-piece 16 64
33 ; CHECK: 0x00000031: Beginning address offset: [[START]]
34 ; CHECK: Ending address offset: [[END]]
35 ; CHECK: Location description: 10 c3 eb a3 82 04
36 ; constu ...
37 source_filename = "test.c"
38 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
39 target triple = "x86_64-apple-macosx10.11.0"
40
41 ; Function Attrs: nounwind ssp uwtable
42 define void @foo() #0 !dbg !4 {
43 entry:
44 tail call void (...) @barrier() #3, !dbg !16
45 tail call void @llvm.dbg.value(metadata float 0x40091EB860000000, i64 0, metadata !8, metadata !17), !dbg !18
46 tail call void @llvm.dbg.value(metadata x86_fp80 0xK4000C8F5C28F5C28F800, i64 0, metadata !10, metadata !17), !dbg !19
47 tail call void (...) @barrier() #3, !dbg !20
48 ret void, !dbg !21
49 }
50
51 declare void @barrier(...)
52
53 ; Function Attrs: nounwind readnone
54 declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
55
56 attributes #0 = { nounwind ssp uwtable }
57 attributes #2 = { nounwind readnone }
58 attributes #3 = { nounwind }
59
60 !llvm.dbg.cu = !{!0}
61 !llvm.module.flags = !{!12, !13, !14}
62 !llvm.ident = !{!15}
63
64 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 265328) (llvm/trunk 265330)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, subprograms: !3)
65 !1 = !DIFile(filename: "test.c", directory: "/Volumes/Data/radar/25448338")
66 !2 = !{}
67 !3 = !{!4}
68 !4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: true, variables: !7)
69 !5 = !DISubroutineType(types: !6)
70 !6 = !{null}
71 !7 = !{!8, !10}
72 !8 = !DILocalVariable(name: "f", scope: !4, file: !1, line: 5, type: !9)
73 !9 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float)
74 !10 = !DILocalVariable(name: "ld", scope: !4, file: !1, line: 6, type: !11)
75 !11 = !DIBasicType(name: "long double", size: 128, align: 128, encoding: DW_ATE_float)
76 !12 = !{i32 2, !"Dwarf Version", i32 2}
77 !13 = !{i32 2, !"Debug Info Version", i32 3}
78 !14 = !{i32 1, !"PIC Level", i32 2}
79 !15 = !{!"clang version 3.9.0 (trunk 265328) (llvm/trunk 265330)"}
80 !16 = !DILocation(line: 7, column: 3, scope: !4)
81 !17 = !DIExpression()
82 !18 = !DILocation(line: 5, column: 9, scope: !4)
83 !19 = !DILocation(line: 6, column: 15, scope: !4)
84 !20 = !DILocation(line: 10, column: 3, scope: !4)
85 !21 = !DILocation(line: 11, column: 1, scope: !4)