return ConcreteVariables.back().get();
}
-// Determine whether this DBG_VALUE is valid at the beginning of the function.
-static bool validAtEntry(const MachineInstr *MInsn) {
- auto MBB = MInsn->getParent();
- // Is it in the entry basic block?
- if (!MBB->pred_empty())
+/// Determine whether a *singular* DBG_VALUE is valid for the entirety of its
+/// enclosing lexical scope. The check ensures there are no other instructions
+/// in the same lexical scope preceding the DBG_VALUE and that its range is
+/// either open or otherwise rolls off the end of the scope.
+static bool validThroughout(LexicalScopes &LScopes,
+ const MachineInstr *DbgValue,
+ const MachineInstr *RangeEnd) {
+ assert(DbgValue->getDebugLoc() && "DBG_VALUE without a debug location");
+ auto MBB = DbgValue->getParent();
+ auto DL = DbgValue->getDebugLoc();
+ auto *LScope = LScopes.findLexicalScope(DL);
+ // Scope doesn't exist; this is a dead DBG_VALUE.
+ if (!LScope)
return false;
- for (MachineBasicBlock::const_reverse_iterator I(MInsn); I != MBB->rend(); ++I)
- if (!(I->isDebugValue() || I->getFlag(MachineInstr::FrameSetup)))
+ auto &LSRange = LScope->getRanges();
+ if (LSRange.size() == 0)
+ return false;
+
+ // Determine if the DBG_VALUE is valid at the beginning of its lexical block.
+ const MachineInstr *LScopeBegin = LSRange.front().first;
+ // Early exit if the lexical scope begins outside of the current block.
+ if (LScopeBegin->getParent() != MBB)
+ return false;
+ MachineBasicBlock::const_reverse_iterator Pred(DbgValue);
+ for (++Pred; Pred != MBB->rend(); ++Pred) {
+ if (Pred->getFlag(MachineInstr::FrameSetup))
+ break;
+ auto PredDL = Pred->getDebugLoc();
+ if (!PredDL || Pred->isDebugValue())
+ continue;
+ // Check whether the instruction preceding the DBG_VALUE is in the same
+ // (sub)scope as the DBG_VALUE.
+ if (DL->getScope() == PredDL->getScope() ||
+ LScope->dominates(LScopes.findLexicalScope(PredDL)))
return false;
- return true;
+ }
+
+ // If the range of the DBG_VALUE is open-ended, report success.
+ if (!RangeEnd)
+ return true;
+
+ // Fail if there are instructions belonging to our scope in another block.
+ const MachineInstr *LScopeEnd = LSRange.back().second;
+ if (LScopeEnd->getParent() != MBB)
+ return false;
+
+ // Single, constant DBG_VALUEs in the prologue are promoted to be live
+ // throughout the function. This is a hack, presumably for DWARF v2 and not
+ // necessarily correct. It would be much better to use a dbg.declare instead
+ // if we know the constant is live throughout the scope.
+ if (DbgValue->getOperand(0).isImm() && MBB->pred_empty())
+ return true;
+
+ return false;
}
// Find variables for each lexical scope.
const MachineInstr *MInsn = Ranges.front().first;
assert(MInsn->isDebugValue() && "History must begin with debug value");
- // Check if there is a single DBG_VALUE, valid throughout the function.
- // A single constant is also considered valid for the entire function.
+ // Check if there is a single DBG_VALUE, valid throughout the var's scope.
if (Ranges.size() == 1 &&
- (MInsn->getOperand(0).isImm() ||
- (validAtEntry(MInsn) && Ranges.front().second == nullptr))) {
+ validThroughout(LScopes, MInsn, Ranges.front().second)) {
RegVar->initializeDbgValue(MInsn);
continue;
}
--- /dev/null
+; RUN: %llc_dwarf -filetype=obj < %s | llvm-dwarfdump - | FileCheck %s
+; Generated at -O2 from:
+; bool c();
+; void f();
+; bool start() {
+; bool result = c();
+; if (!c()) {
+; result = false;
+; goto exit;
+; }
+; f();
+; result = true;
+; exit:
+; return result;
+; }
+;
+; The constant should NOT be available for the entire function.
+; CHECK-NOT: DW_AT_const_value
+; CHECK: .debug_loc
+; CHECK: Location description: 10 01 9f
+; constu 0x00000001, stack-value
+source_filename = "test.ii"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+; Function Attrs: noimplicitfloat noredzone nounwind optsize
+define zeroext i1 @_Z5startv() local_unnamed_addr #0 !dbg !7 {
+entry:
+ %call = tail call zeroext i1 @_Z1cv() #3, !dbg !13
+ %call1 = tail call zeroext i1 @_Z1cv() #3, !dbg !14
+ br i1 %call1, label %if.end, label %exit, !dbg !16
+
+if.end: ; preds = %entry
+ tail call void @_Z1fv() #3, !dbg !17
+ tail call void @llvm.dbg.value(metadata i8 1, i64 0, metadata !12, metadata !18), !dbg !19
+ br label %exit, !dbg !20
+
+exit: ; preds = %entry, %if.end
+ %result.0 = phi i1 [ true, %if.end ], [ false, %entry ]
+ ret i1 %result.0, !dbg !21
+}
+
+; Function Attrs: noimplicitfloat noredzone optsize
+declare zeroext i1 @_Z1cv() local_unnamed_addr #1
+
+; Function Attrs: noimplicitfloat noredzone optsize
+declare void @_Z1fv() local_unnamed_addr #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
+
+attributes #0 = { noimplicitfloat noredzone nounwind optsize }
+attributes #1 = { noimplicitfloat noredzone optsize }
+attributes #2 = { nounwind readnone speculatable }
+attributes #3 = { nobuiltin noimplicitfloat noredzone nounwind optsize }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 303873) (llvm/trunk 303897)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "test.ii", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 5.0.0 (trunk 303873) (llvm/trunk 303897)"}
+!7 = distinct !DISubprogram(name: "start", linkageName: "_Z5startv", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !11)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10}
+!10 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
+!11 = !{!12}
+!12 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 4, type: !10)
+!13 = !DILocation(line: 4, column: 17, scope: !7)
+!14 = !DILocation(line: 5, column: 8, scope: !15)
+!15 = distinct !DILexicalBlock(scope: !7, file: !1, line: 5, column: 7)
+!16 = !DILocation(line: 5, column: 7, scope: !7)
+!17 = !DILocation(line: 9, column: 3, scope: !7)
+!18 = !DIExpression()
+!19 = !DILocation(line: 4, column: 8, scope: !7)
+!20 = !DILocation(line: 10, column: 3, scope: !7)
+!21 = !DILocation(line: 12, column: 3, scope: !7)
; RUN: %llc_dwarf -O0 -filetype=obj %s -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
; Use correct signedness when emitting constants of derived (sugared) types.
-; Test compiled to IR from clang with -O1 and the following source:
-
-; void func(int);
-; void func(unsigned);
-; void func(char16_t);
-; int main() {
-; const int i = 42;
-; func(i);
-; const unsigned j = 117;
-; func(j);
-; char16_t c = 7;
-; func(c);
-; }
-
; CHECK: DW_AT_const_value [DW_FORM_sdata] (42)
; CHECK: DW_AT_const_value [DW_FORM_udata] (117)
; CHECK: DW_AT_const_value [DW_FORM_udata] (7)
; Function Attrs: uwtable
-define i32 @main() #0 !dbg !4 {
+define void @main() #0 !dbg !4 {
entry:
tail call void @llvm.dbg.value(metadata i32 42, i64 0, metadata !10, metadata !DIExpression()), !dbg !21
- tail call void @_Z4funci(i32 42), !dbg !22
tail call void @llvm.dbg.value(metadata i32 117, i64 0, metadata !12, metadata !DIExpression()), !dbg !24
- tail call void @_Z4funcj(i32 117), !dbg !25
tail call void @llvm.dbg.value(metadata i16 7, i64 0, metadata !15, metadata !DIExpression()), !dbg !27
- tail call void @_Z4funcDs(i16 zeroext 7), !dbg !28
- ret i32 0, !dbg !29
+ ret void, !dbg !29
}
-declare void @_Z4funci(i32) #1
-
-declare void @_Z4funcj(i32) #1
-
-declare void @_Z4funcDs(i16 zeroext) #1
-
; Function Attrs: nounwind readnone
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
-attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #0 = { uwtable }
attributes #2 = { nounwind readnone }
!llvm.dbg.cu = !{!0}
-# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
+# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump --debug-dump=info - | FileCheck %s
# CHECK: .debug_info contents:
# CHECK: DW_TAG_variable
-# CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] ([[OFS:.*]])
-# CHECK-NEXT: DW_AT_name {{.*}}"dh"
-# CHECK: .debug_loc contents:
-# CHECK: [[OFS]]: Beginning address offset: 0x0000000000000002
-# CHECK: Ending address offset: 0x000000000000000c
-# CHECK: Location description: 51 9d 08 08
# rdx, bit-piece 8 8
+# CHECK-NEXT: DW_AT_location {{.*}} 51 9d 08 08
+# CHECK-NEXT: DW_AT_name {{.*}}"dh"
--- |
; Manually created after:
; char f(int i) {
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin8"
+; Test that consecutive, identical DBG_VALUEs are merged.
;CHECK: DW_AT_location{{.*}}(<0x1> 55 )
%0 = type { i64, i1 }
br i1 undef, label %bb2, label %bb4, !dbg !22
bb2: ; preds = %entry
+ tail call void @llvm.dbg.value(metadata i128 %u, i64 0, metadata !14, metadata !DIExpression()), !dbg !15
br label %bb4, !dbg !23
bb4: ; preds = %bb2, %entry
; RUN: llc -filetype=obj -o %t.o %s
-; RUN: llvm-dwarfdump -debug-dump=info %t.o | FileCheck %s
+; RUN: llvm-dwarfdump %t.o | FileCheck %s
; Testcase generated using 'clang -g -O2 -S -emit-llvm' from the following:
;; void sink(void);
;; }
; Check that we have formal parameters for 'a' in both inlined subroutines.
+; CHECK: .debug_info
; CHECK: DW_TAG_inlined_subroutine
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} "bar"
; CHECK: DW_TAG_formal_parameter
; CHECK: DW_TAG_inlined_subroutine
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} "bar"
; CHECK: DW_TAG_formal_parameter
-; CHECK-NEXT: DW_AT_const_value
+; CHECK-NEXT: DW_AT_location [DW_FORM_data4] (0x00000000)
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} "a"
-
+;
+; CHECK: .debug_loc
+; CHECK: Location description: 11 00
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin"
ret void, !dbg !24
}
-declare void @sink() #1
+declare void @sink()
; Function Attrs: nounwind readnone
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
-attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #0 = { nounwind ssp uwtable }
attributes #2 = { nounwind readnone }
attributes #3 = { nounwind }
; CHECK: debug_info contents
; 0x74 is DW_OP_breg4, showing that the parameter is accessed indirectly
-; (with a zero offset) from the register parameter
-; CHECK: DW_AT_location [DW_FORM_data4] ([[F_LOC:0x[0-9]*]])
+; (with a zero offset) from the register parameter.
+; CHECK: DW_AT_location {{.*}} 74 00 06
+
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name{{.*}} = "f"
;
; CHECK: DW_AT_name{{.*}} = "g"
;
; CHECK: debug_loc contents
-; CHECK: [[F_LOC]]: Beginning
-; CHECK-NEXT: Ending
-; CHECK-NEXT: Location description: 74 00
; CHECK: [[G_LOC]]: Beginning
; CHECK-NEXT: Ending
; CHECK-NEXT: Location description: 74 00
ret void, !dbg !32
}
-declare void @_ZN7pr147634sinkEPv(i8*) #2
+declare void @_ZN7pr147634sinkEPv(i8*)
-attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #0 = { uwtable }
attributes #1 = { nounwind readnone }
-attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!21, !33}
; CHECK-NEXT: DW_AT_location [DW_FORM_data4] ([[LOC1:.*]])
; CHECK-NEXT: DW_AT_name {{.*}}"outer"
; CHECK: DW_TAG_variable
-; CHECK-NEXT: DW_AT_location [DW_FORM_data4] ([[LOC2:.*]])
+; CHECK-NEXT: DW_AT_location
+; rsi, piece 0x00000004
+; CHECK-SAME: 54 93 04
; CHECK-NEXT: "i1"
;
; CHECK: .debug_loc
; CHECK: Beginning address offset: 0x0000000000000004
; CHECK-NEXT: Ending address offset: 0x0000000000000008
; CHECK-NEXT: Location description: 55 93 08 93 04 54 93 04
-; CHECK: [[LOC2]]: Beginning address offset: 0x0000000000000004
-; CHECK-NEXT: Ending address offset: 0x0000000000000008
-; rsi, piece 0x00000004
-; CHECK-NEXT: Location description: 54 93 04
;
; ModuleID = '/Volumes/Data/llvm/test/DebugInfo/X86/sroasplit-2.ll'
call void @llvm.dbg.declare(metadata !{null}, metadata !27, metadata !28), !dbg !26
call void @llvm.dbg.value(metadata i64 %outer.coerce1, i64 0, metadata !29, metadata !30), !dbg !26
call void @llvm.dbg.declare(metadata !{null}, metadata !31, metadata !32), !dbg !26
+ ; The 'trunc' generates no extra code, thus i1 is visible throughout its scope.
%outer.sroa.1.8.extract.trunc = trunc i64 %outer.coerce1 to i32, !dbg !33
call void @llvm.dbg.value(metadata i32 %outer.sroa.1.8.extract.trunc, i64 0, metadata !34, metadata !35), !dbg !33
%outer.sroa.1.12.extract.shift = lshr i64 %outer.coerce1, 32, !dbg !33
-; RUN: llc -mtriple=x86_64-apple-macosx10.9.0 -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=all - | FileCheck %s
+; RUN: llc -mtriple=x86_64-apple-macosx10.9.0 -filetype=obj -O0 < %s \
+; RUN: | llvm-dwarfdump -debug-dump=info - | FileCheck %s
; ModuleID = 'aggregate-indirect-arg.cpp'
; extracted from debuginfo-tests/aggregate-indirect-arg.cpp
; CHECK: DW_AT_name {{.*}} "this"
; CHECK-NOT: DW_TAG_subprogram
; CHECK: DW_TAG_formal_parameter
-; CHECK-NEXT: DW_AT_location [DW_FORM_data4] (0x00000000)
-; CHECK-NEXT: DW_AT_name {{.*}} "v"
-; CHECK: .debug_loc contents:
+; CHECK-NEXT: DW_AT_location
; rsi+0
-; CHECK: Location description: 74 00
+; CHECK-SAME: 74 00
+; CHECK-NEXT: DW_AT_name {{.*}} "v"
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.9.0"
; RUN: llc -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM
-; RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
+; RUN: llc -filetype=obj -o - %s | llvm-dwarfdump --debug-dump=info - | FileCheck %s
;
; Generated at -O2 from:
; struct B;
; modified by the debugger.
;
; ASM: [DW_OP_stack_value]
-; CHECK: Location description: 70 00 9f
+; CHECK: DW_AT_location {{.*}} 70 00 9f
; rax+0, stack-value
source_filename = "ab.cpp"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"