Files
clang-p2996/llvm/test/DebugInfo/ARM/entry-value-multi-byte-expr.ll
Jeremy Morse 1575583f2a [LiveDebugValues][InstrRef][2/2] Emit entry value variable locations
This patch adds support to the instruction-referencing LiveDebugValues
implementation for emitting entry values. The instruction referencing
implementations tracking by value rather than location means that we can
get around two of the issues with VarLocs. DBG_VALUE instructions that
re-assign the same value to a variable are no longer a problem, because we
can "see through" to the value being assigned. We also don't need to do
anything special during the dataflow stages: the "variable value problem"
doesn't need to know whether a value is available most of the time, and the
times it deoes need to know are always when entry values need to be
terminated.

The patch modifies the "TransferTracker" class, adding methods to identify
when a variable ias an entry value candidate, and when a machine value is
an entry value. recoverAsEntryValue tests these two things and emits an
entry-value expression if they're true. It's used when we clobber or
otherwise lose a value and can't find a replacement location for the value
it contained.

Differential Revision: https://reviews.llvm.org/D88406
2021-06-30 23:07:39 +01:00

93 lines
3.8 KiB
LLVM

; RUN: llc -debug-entry-values -filetype=asm -o - %s | FileCheck %s
; RUN: llc -force-instr-ref-livedebugvalues=1 -debug-entry-values -filetype=asm -o - %s | FileCheck %s
; Verify that the size operands of the DW_OP_GNU_entry_value operations are
; correct for the multi-byte DW_OP_regx expressions.
; Based on the following C reproducer:
;
; extern void clobber();
; double global;
; int f(double a, double b) {
; global = a + b;
; clobber();
; return 1;
; }
; This test checks the assembly output rather than the output from
; llvm-dwarfdump, as the latter printed the DW_OP_regx D0 correctly, even
; though the entry value's size operand did not fully cover that:
; DW_OP_GNU_entry_value(DW_OP_regx D0), DW_OP_stack_value
;
; whereas readelf interpreted it as an DW_OP_GNU_entry_value covering one byte,
; resulting in garbage data:
;
; DW_OP_GNU_entry_value: (DW_OP_regx: 0 (r0)); DW_OP_breg16 (r16): 2; DW_OP_stack_value
; CHECK: .byte 243 @ DW_OP_GNU_entry_value
; CHECK-NEXT: .byte 3 @ 3
; CHECK-NEXT: .byte 144 @ DW_OP_regx
; CHECK-NEXT: .byte 128 @ 256
; CHECK-NEXT: .byte 2 @
; CHECK-NEXT: .byte 159 @ DW_OP_stack_value
; CHECK: .byte 243 @ DW_OP_GNU_entry_value
; CHECK-NEXT: .byte 3 @ 3
; CHECK-NEXT: .byte 144 @ DW_OP_regx
; CHECK-NEXT: .byte 129 @ 257
; CHECK-NEXT: .byte 2 @
; CHECK-NEXT: .byte 159 @ DW_OP_stack_value
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
target triple = "armv7-unknown-unknown"
@global = common global double 0.000000e+00, align 8, !dbg !0
; Function Attrs: nounwind
define arm_aapcs_vfpcc i32 @f(double %a, double %b) #0 !dbg !12 {
entry:
call void @llvm.dbg.value(metadata double %a, metadata !17, metadata !DIExpression()), !dbg !19
call void @llvm.dbg.value(metadata double %b, metadata !18, metadata !DIExpression()), !dbg !19
%add = fadd double %a, %b, !dbg !20
store double %add, double* @global, align 8, !dbg !20
tail call arm_aapcs_vfpcc void @clobber(), !dbg !21
ret i32 1, !dbg !22
}
declare arm_aapcs_vfpcc void @clobber()
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
attributes #0 = { nounwind }
attributes #1 = { nounwind readnone speculatable willreturn }
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!7, !8, !9, !10}
!llvm.ident = !{!11}
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "global", scope: !2, file: !3, line: 4, type: !6, isLocal: false, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
!3 = !DIFile(filename: "entry-value-multi-byte-expr.c", directory: "/")
!4 = !{}
!5 = !{!0}
!6 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)
!7 = !{i32 2, !"Dwarf Version", i32 4}
!8 = !{i32 2, !"Debug Info Version", i32 3}
!9 = !{i32 1, !"wchar_size", i32 4}
!10 = !{i32 1, !"min_enum_size", i32 4}
!11 = !{!"clang version 10.0.0"}
!12 = distinct !DISubprogram(name: "f", scope: !3, file: !3, line: 6, type: !13, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !16)
!13 = !DISubroutineType(types: !14)
!14 = !{!15, !6, !6}
!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!16 = !{!17, !18}
!17 = !DILocalVariable(name: "a", arg: 1, scope: !12, file: !3, line: 6, type: !6)
!18 = !DILocalVariable(name: "b", arg: 2, scope: !12, file: !3, line: 6, type: !6)
!19 = !DILocation(line: 0, scope: !12)
!20 = !DILocation(line: 7, scope: !12)
!21 = !DILocation(line: 8, scope: !12)
!22 = !DILocation(line: 9, scope: !12)