forked from OSchip/llvm-project
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> llvm-svn: 265760
This commit is contained in:
parent
267185ec92
commit
3e9c88753b
|
@ -1438,10 +1438,10 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
|
|||
DwarfExpr.AddMachineRegExpression(Expr, Loc.getReg(),
|
||||
PieceOffsetInBits);
|
||||
}
|
||||
} else if (Value.isConstantFP()) {
|
||||
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
|
||||
DwarfExpr.AddUnsignedConstant(RawBytes);
|
||||
}
|
||||
// else ... ignore constant fp. There is not any good way to
|
||||
// to represent them here in dwarf.
|
||||
// FIXME: ^
|
||||
}
|
||||
|
||||
void DebugLocEntry::finalize(const AsmPrinter &AP,
|
||||
|
|
|
@ -159,29 +159,37 @@ bool DwarfExpression::AddMachineRegPiece(unsigned MachineReg,
|
|||
return CurPos > PieceOffsetInBits;
|
||||
}
|
||||
|
||||
void DwarfExpression::AddStackValue() {
|
||||
if (DwarfVersion >= 4)
|
||||
EmitOp(dwarf::DW_OP_stack_value);
|
||||
}
|
||||
|
||||
void DwarfExpression::AddSignedConstant(int Value) {
|
||||
EmitOp(dwarf::DW_OP_consts);
|
||||
EmitSigned(Value);
|
||||
// The proper way to describe a constant value is
|
||||
// DW_OP_constu <const>, DW_OP_stack_value.
|
||||
// Unfortunately, DW_OP_stack_value was not available until DWARF-4,
|
||||
// so we will continue to generate DW_OP_constu <const> for DWARF-2
|
||||
// and DWARF-3. Technically, this is incorrect since DW_OP_const <const>
|
||||
// actually describes a value at a constant addess, not a constant value.
|
||||
// However, in the past there was no better way to describe a constant
|
||||
// value, so the producers and consumers started to rely on heuristics
|
||||
// to disambiguate the value vs. location status of the expression.
|
||||
// See PR21176 for more details.
|
||||
if (DwarfVersion >= 4)
|
||||
EmitOp(dwarf::DW_OP_stack_value);
|
||||
AddStackValue();
|
||||
}
|
||||
|
||||
void DwarfExpression::AddUnsignedConstant(unsigned Value) {
|
||||
EmitOp(dwarf::DW_OP_constu);
|
||||
EmitUnsigned(Value);
|
||||
// cf. comment in DwarfExpression::AddSignedConstant().
|
||||
if (DwarfVersion >= 4)
|
||||
EmitOp(dwarf::DW_OP_stack_value);
|
||||
AddStackValue();
|
||||
}
|
||||
|
||||
void DwarfExpression::AddUnsignedConstant(APInt Value) {
|
||||
unsigned Size = Value.getBitWidth();
|
||||
const uint64_t *Data = Value.getRawData();
|
||||
|
||||
// Chop it up into 64-bit pieces, because that's the maximum that
|
||||
// AddUnsignedConstant takes.
|
||||
unsigned Offset = 0;
|
||||
while (Offset < Size) {
|
||||
AddUnsignedConstant(*Data++);
|
||||
if (Offset == 0 && Size <= 64)
|
||||
break;
|
||||
AddOpPiece(std::min(Size-Offset, 64u), Offset);
|
||||
Offset += 64;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned getOffsetOrZero(unsigned OffsetInBits,
|
||||
|
|
|
@ -61,6 +61,19 @@ public:
|
|||
void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
|
||||
/// Emit a shift-right dwarf expression.
|
||||
void AddShr(unsigned ShiftBy);
|
||||
/// Emit a DW_OP_stack_value, if supported.
|
||||
///
|
||||
/// The proper way to describe a constant value is
|
||||
/// DW_OP_constu <const>, DW_OP_stack_value.
|
||||
/// Unfortunately, DW_OP_stack_value was not available until DWARF-4,
|
||||
/// so we will continue to generate DW_OP_constu <const> for DWARF-2
|
||||
/// and DWARF-3. Technically, this is incorrect since DW_OP_const <const>
|
||||
/// actually describes a value at a constant addess, not a constant value.
|
||||
/// However, in the past there was no better way to describe a constant
|
||||
/// value, so the producers and consumers started to rely on heuristics
|
||||
/// to disambiguate the value vs. location status of the expression.
|
||||
/// See PR21176 for more details.
|
||||
void AddStackValue();
|
||||
|
||||
/// Emit an indirect dwarf register operation for the given machine register.
|
||||
/// \return false if no DWARF register exists for MachineReg.
|
||||
|
@ -87,6 +100,8 @@ public:
|
|||
void AddSignedConstant(int Value);
|
||||
/// Emit an unsigned constant.
|
||||
void AddUnsignedConstant(unsigned Value);
|
||||
/// Emit an unsigned constant.
|
||||
void AddUnsignedConstant(APInt Value);
|
||||
|
||||
/// \brief Emit an entire expression on top of a machine register location.
|
||||
///
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
; RUN: llc -mtriple=x86_64-apple-macosx <%s | FileCheck %s
|
||||
; Test that we don't generate empty .debug_loc entries. Originally, there were
|
||||
; two empty .debug_loc entries for 'a' in an otherwise empty .debug_loc list.
|
||||
;
|
||||
; CHECK: .section __DWARF,__debug_loc,regular,debug
|
||||
; CHECK-NEXT: Lsection_debug_loc:
|
||||
; CHECK-NEXT: .section __DWARF,__debug_abbrev,regular,debug
|
||||
;
|
||||
; Test that the variable stuck around.
|
||||
; CHECK: .section __DWARF,__debug_info,regular,debug
|
||||
; CHECK: DW_TAG_variable
|
||||
; CHECK-NOT: DW_AT_location
|
||||
|
||||
; Generated using clang -cc1 with the following args:
|
||||
;
|
||||
; -triple x86_64-apple-macosx -emit-llvm -gdwarf-4 -O1
|
||||
;
|
||||
; From this testcase:
|
||||
;
|
||||
;; void fn1() {
|
||||
;; float a = 1;
|
||||
;; for (;;)
|
||||
;; a = 0;
|
||||
;; }
|
||||
|
||||
; Function Attrs: noreturn nounwind readnone
|
||||
define void @_Z3fn1v() #0 !dbg !4 {
|
||||
entry:
|
||||
tail call void @llvm.dbg.value(metadata float 1.000000e+00, i64 0, metadata !9, metadata !14), !dbg !15
|
||||
br label %for.cond, !dbg !16
|
||||
|
||||
for.cond: ; preds = %for.cond, %entry
|
||||
tail call void @llvm.dbg.value(metadata float 0.000000e+00, i64 0, metadata !9, metadata !14), !dbg !15
|
||||
br label %for.cond, !dbg !17
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
|
||||
|
||||
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" }
|
||||
attributes #1 = { nounwind readnone }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!11, !12}
|
||||
!llvm.ident = !{!13}
|
||||
|
||||
!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)
|
||||
!1 = !DIFile(filename: "<stdin>", directory: "/Users/dexonsmith/data/llvm/bootstrap/play/delta2/testcase")
|
||||
!2 = !{}
|
||||
!3 = !{!4}
|
||||
!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)
|
||||
!5 = !DIFile(filename: "t.cpp", directory: "/Users/dexonsmith/data/llvm/bootstrap/play/delta2/testcase")
|
||||
!6 = !DISubroutineType(types: !7)
|
||||
!7 = !{null}
|
||||
!8 = !{!9}
|
||||
!9 = !DILocalVariable(name: "a", scope: !4, file: !5, line: 2, type: !10)
|
||||
!10 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float)
|
||||
!11 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!12 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!13 = !{!"clang version 3.7.0 (trunk 238517) (llvm/trunk 238524)"}
|
||||
!14 = !DIExpression()
|
||||
!15 = !DILocation(line: 2, scope: !4)
|
||||
!16 = !DILocation(line: 3, scope: !4)
|
||||
!17 = !DILocation(line: 3, scope: !18)
|
||||
!18 = distinct !DILexicalBlock(scope: !19, file: !5, line: 3)
|
||||
!19 = distinct !DILexicalBlock(scope: !4, file: !5, line: 3)
|
|
@ -0,0 +1,86 @@
|
|||
; RUN: llc %s -stop-after=livedebugvalues -o %t 2>&1 | FileCheck --check-prefix=SANITY %s
|
||||
; RUN: llc < %s -filetype=obj | llvm-dwarfdump - | FileCheck %s
|
||||
; Test debug_loc support for floating point constants.
|
||||
;
|
||||
; Created from clang -O1:
|
||||
; void barrier();
|
||||
; void foo() {
|
||||
; float f;
|
||||
; long double ld;
|
||||
; barrier();
|
||||
; f = 3.14;
|
||||
; ld = 3.14;
|
||||
; barrier();
|
||||
; }
|
||||
;
|
||||
; SANITY: CALL{{.*}} @barrier
|
||||
; SANITY: DBG_VALUE x86_fp80 0xK4000C8F5C28F5C28F800
|
||||
; SANITY: DBG_VALUE float 0x40091EB860000000
|
||||
; SANITY: TAILJMP{{.*}} @barrier
|
||||
;
|
||||
; CHECK: .debug_info contents:
|
||||
; CHECK: DW_TAG_variable
|
||||
; CHECK-NEXT: DW_AT_location {{.*}} (0x00000000)
|
||||
; CHECK-NEXT: DW_AT_name {{.*}}"ld"
|
||||
; CHECK: DW_TAG_variable
|
||||
; CHECK-NEXT: DW_AT_location {{.*}} (0x00000031)
|
||||
; CHECK-NEXT: DW_AT_name {{.*}}"f"
|
||||
;
|
||||
; CHECK: .debug_loc contents:
|
||||
; CHECK: 0x00000000: Beginning address offset: [[START:.*]]
|
||||
; CHECK: Ending address offset: [[END:.*]]
|
||||
; CHECK: Location description: 10 80 f0 a3 e1 05 93 08 10 80 80 01 9d 10 40
|
||||
; constu ..., piece 8, constu ..., bit-piece 16 64
|
||||
; CHECK: 0x00000031: Beginning address offset: [[START]]
|
||||
; CHECK: Ending address offset: [[END]]
|
||||
; CHECK: Location description: 10 c3 eb a3 82 04
|
||||
; constu ...
|
||||
source_filename = "test.c"
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.11.0"
|
||||
|
||||
; Function Attrs: nounwind ssp uwtable
|
||||
define void @foo() #0 !dbg !4 {
|
||||
entry:
|
||||
tail call void (...) @barrier() #3, !dbg !16
|
||||
tail call void @llvm.dbg.value(metadata float 0x40091EB860000000, i64 0, metadata !8, metadata !17), !dbg !18
|
||||
tail call void @llvm.dbg.value(metadata x86_fp80 0xK4000C8F5C28F5C28F800, i64 0, metadata !10, metadata !17), !dbg !19
|
||||
tail call void (...) @barrier() #3, !dbg !20
|
||||
ret void, !dbg !21
|
||||
}
|
||||
|
||||
declare void @barrier(...)
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
|
||||
|
||||
attributes #0 = { nounwind ssp uwtable }
|
||||
attributes #2 = { nounwind readnone }
|
||||
attributes #3 = { nounwind }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!12, !13, !14}
|
||||
!llvm.ident = !{!15}
|
||||
|
||||
!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)
|
||||
!1 = !DIFile(filename: "test.c", directory: "/Volumes/Data/radar/25448338")
|
||||
!2 = !{}
|
||||
!3 = !{!4}
|
||||
!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: true, variables: !7)
|
||||
!5 = !DISubroutineType(types: !6)
|
||||
!6 = !{null}
|
||||
!7 = !{!8, !10}
|
||||
!8 = !DILocalVariable(name: "f", scope: !4, file: !1, line: 5, type: !9)
|
||||
!9 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float)
|
||||
!10 = !DILocalVariable(name: "ld", scope: !4, file: !1, line: 6, type: !11)
|
||||
!11 = !DIBasicType(name: "long double", size: 128, align: 128, encoding: DW_ATE_float)
|
||||
!12 = !{i32 2, !"Dwarf Version", i32 2}
|
||||
!13 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!14 = !{i32 1, !"PIC Level", i32 2}
|
||||
!15 = !{!"clang version 3.9.0 (trunk 265328) (llvm/trunk 265330)"}
|
||||
!16 = !DILocation(line: 7, column: 3, scope: !4)
|
||||
!17 = !DIExpression()
|
||||
!18 = !DILocation(line: 5, column: 9, scope: !4)
|
||||
!19 = !DILocation(line: 6, column: 15, scope: !4)
|
||||
!20 = !DILocation(line: 10, column: 3, scope: !4)
|
||||
!21 = !DILocation(line: 11, column: 1, scope: !4)
|
Loading…
Reference in New Issue